Commit 52802867 authored by CZ1004's avatar CZ1004

Merge branch 'develop_0409' into Advertisement

* develop_0409:
  邮箱界面
parents 7a44f2d6 f78b7dc5
...@@ -77,6 +77,13 @@ ...@@ -77,6 +77,13 @@
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
041E22DC2DCCD63B0028E917 /* Exceptions for "widget" folder in "PhoneManager" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
widgetLockSreenView.swift,
);
target = EB388E5A2D8A61A800629B0D /* PhoneManager */;
};
0496DF032D9E3F59005B2834 /* Exceptions for "widget" folder in "widgetExtension" target */ = { 0496DF032D9E3F59005B2834 /* Exceptions for "widget" folder in "widgetExtension" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet; isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = ( membershipExceptions = (
...@@ -104,6 +111,7 @@ ...@@ -104,6 +111,7 @@
0496DEF52D9E3F58005B2834 /* widget */ = { 0496DEF52D9E3F58005B2834 /* widget */ = {
isa = PBXFileSystemSynchronizedRootGroup; isa = PBXFileSystemSynchronizedRootGroup;
exceptions = ( exceptions = (
041E22DC2DCCD63B0028E917 /* Exceptions for "widget" folder in "PhoneManager" target */,
0496DF032D9E3F59005B2834 /* Exceptions for "widget" folder in "widgetExtension" target */, 0496DF032D9E3F59005B2834 /* Exceptions for "widget" folder in "widgetExtension" target */,
); );
path = widget; path = widget;
...@@ -580,10 +588,12 @@ ...@@ -580,10 +588,12 @@
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = PhoneManager/Info.plist; INFOPLIST_FILE = PhoneManager/Info.plist;
INFOPLIST_KEY_NSCameraUsageDescription = "We need to obtain your camera permission in order to save the photos you take in the private album feature"; INFOPLIST_KEY_NSCameraUsageDescription = "We need to obtain your camera permission in order to save the photos you take in the private album feature";
INFOPLIST_KEY_NSContactsUsageDescription = "Phone Manager needs access to your contacts to find and merge duplicate contacts";
INFOPLIST_KEY_NSLocalNetworkUsageDescription = "We need to access the network to load content"; INFOPLIST_KEY_NSLocalNetworkUsageDescription = "We need to access the network to load content";
INFOPLIST_KEY_NSMicrophoneUsageDescription = "We need to obtain your microphone permission in order to use it when shooting videos in the private album feature"; INFOPLIST_KEY_NSMicrophoneUsageDescription = "We need to obtain your microphone permission in order to use it when shooting videos in the private album feature";
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "We need to access your album in order to find the photos you want to change and update them"; INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "We need to access your album in order to find the photos you want to change and update them";
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "We need to access your album in order to find the photos you want to change and update them"; INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "We need to access your album in order to find the photos you want to change and update them";
INFOPLIST_KEY_NSUserTrackingUsageDescription = "We need your permission to track your usage habits in order to provide a more personalized advertising experience";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main; INFOPLIST_KEY_UIMainStoryboardFile = Main;
...@@ -626,10 +636,12 @@ ...@@ -626,10 +636,12 @@
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = PhoneManager/Info.plist; INFOPLIST_FILE = PhoneManager/Info.plist;
INFOPLIST_KEY_NSCameraUsageDescription = "We need to obtain your camera permission in order to save the photos you take in the private album feature"; INFOPLIST_KEY_NSCameraUsageDescription = "We need to obtain your camera permission in order to save the photos you take in the private album feature";
INFOPLIST_KEY_NSContactsUsageDescription = "Phone Manager needs access to your contacts to find and merge duplicate contacts";
INFOPLIST_KEY_NSLocalNetworkUsageDescription = "We need to access the network to load content"; INFOPLIST_KEY_NSLocalNetworkUsageDescription = "We need to access the network to load content";
INFOPLIST_KEY_NSMicrophoneUsageDescription = "We need to obtain your microphone permission in order to use it when shooting videos in the private album feature"; INFOPLIST_KEY_NSMicrophoneUsageDescription = "We need to obtain your microphone permission in order to use it when shooting videos in the private album feature";
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "We need to access your album in order to find the photos you want to change and update them"; INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "We need to access your album in order to find the photos you want to change and update them";
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "We need to access your album in order to find the photos you want to change and update them"; INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "We need to access your album in order to find the photos you want to change and update them";
INFOPLIST_KEY_NSUserTrackingUsageDescription = "We need your permission to track your usage habits in order to provide a more personalized advertising experience";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main; INFOPLIST_KEY_UIMainStoryboardFile = Main;
......
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "button_switch_off.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "button_switch_off@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "button_switch_off@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "button_switch_on.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "button_switch_on@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "button_switch_on@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "emailSmall.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_delete_duplicates.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_delete_duplicates@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_delete_duplicates@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_sel_com.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_sel_com@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_sel_com@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_switch_email.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_switch_email@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_switch_email@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_unsel_com.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_unsel_com@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_unsel_com@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_unsel_com_red.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_unsel_com_red@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_unsel_com_red@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "icon_add.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "icon_add@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "icon_add@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "icon_left_setting_grey.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "icon_left_setting_grey@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "icon_left_setting_grey@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "img_email.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "img_email@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "img_email@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
//
// 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()
}
}
<?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="EmailCleanListViewCell" customModule="PhoneManager" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="356" height="101"/>
<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="356" height="101"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bse-XL-ULx">
<rect key="frame" x="15" y="0.0" width="326" height="89"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="XwR-Ch-R1t">
<rect key="frame" x="6" y="15.000000000000004" width="44" height="44.333333333333343"/>
<constraints>
<constraint firstAttribute="width" constant="44" id="waN-0f-ZFP"/>
</constraints>
<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="HYp-JA-LKq"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="G" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Lkh-fE-u5M">
<rect key="frame" x="50" y="17.333333333333329" width="40" height="40"/>
<color key="backgroundColor" red="0.0" green="0.50980392156862742" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="WQp-b1-7L9"/>
<constraint firstAttribute="height" constant="40" id="YZo-Rf-iJH"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="heavy" pointSize="20"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="Radius">
<real key="value" value="20"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</label>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="tF1-pU-1Ak">
<rect key="frame" x="100" y="15.666666666666668" width="216" height="53.333333333333329"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="aXC-da-48n">
<rect key="frame" x="0.0" y="0.0" width="216" height="19.333333333333332"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="xWb-J8-Ui7">
<rect key="frame" x="0.0" y="0.0" width="102.33333333333333" height="19.333333333333332"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Fi7-Jr-Qip">
<rect key="frame" x="0.0" y="6.6666666666666661" width="6" height="6"/>
<color key="backgroundColor" red="0.32156862745098036" green="0.7803921568627451" blue="0.46274509803921571" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="6" id="PIU-b3-pWr"/>
<constraint firstAttribute="width" constant="6" id="QEp-ES-1VD"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="Radius">
<real key="value" value="3"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
<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="49v-3u-EtJ">
<rect key="frame" x="8" y="0.0" width="94.333333333333329" height="19.333333333333332"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" translatesAutoresizingMaskIntoConstraints="NO" id="5Cl-XH-rD8">
<rect key="frame" x="166" y="3.0000000000000018" width="50" height="12.999999999999998"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="11 Nov" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2zo-ld-bPP">
<rect key="frame" x="0.0" y="0.0" width="37" height="13"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<color key="textColor" red="0.70196078431372544" green="0.70196078431372544" blue="0.70196078431372544" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_left_setting_grey" translatesAutoresizingMaskIntoConstraints="NO" id="ubl-ns-bXJ">
<rect key="frame" x="37" y="0.0" width="13" height="13"/>
<constraints>
<constraint firstAttribute="width" constant="13" id="YdB-iz-Nwc"/>
<constraint firstAttribute="width" secondItem="ubl-ns-bXJ" secondAttribute="height" multiplier="1:1" id="nFl-sn-e8h"/>
</constraints>
</imageView>
</subviews>
</stackView>
</subviews>
</stackView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Google Payments:您的付款处于暂停状..." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8Mr-iL-2qm">
<rect key="frame" x="0.0" y="21.333333333333336" width="216" height="15.666666666666664"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Google Payments:您的付款处于暂停状..." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="S8d-tj-cjO">
<rect key="frame" x="0.0" y="39" width="216" height="14.333333333333336"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<color key="textColor" red="0.70196078431372544" green="0.70196078431372544" blue="0.70196078431372544" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" red="0.94901960780000005" green="0.96470588239999999" blue="0.98823529409999999" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
<constraints>
<constraint firstItem="Lkh-fE-u5M" firstAttribute="centerY" secondItem="XwR-Ch-R1t" secondAttribute="centerY" id="4mE-mu-PuP"/>
<constraint firstItem="tF1-pU-1Ak" firstAttribute="leading" secondItem="Lkh-fE-u5M" secondAttribute="trailing" constant="10" id="LDV-M1-DPF"/>
<constraint firstItem="XwR-Ch-R1t" firstAttribute="top" secondItem="bse-XL-ULx" secondAttribute="top" constant="15" id="Tgz-Fy-6I4"/>
<constraint firstItem="tF1-pU-1Ak" firstAttribute="centerY" secondItem="Lkh-fE-u5M" secondAttribute="centerY" constant="5" id="ZPF-Cu-F3P"/>
<constraint firstAttribute="height" constant="89" id="eCz-de-gng"/>
<constraint firstItem="Lkh-fE-u5M" firstAttribute="leading" secondItem="XwR-Ch-R1t" secondAttribute="trailing" id="eMG-P8-8VY"/>
<constraint firstAttribute="trailing" secondItem="tF1-pU-1Ak" secondAttribute="trailing" constant="10" id="h9H-l8-3oO"/>
<constraint firstItem="XwR-Ch-R1t" firstAttribute="leading" secondItem="bse-XL-ULx" secondAttribute="leading" constant="6" id="jY4-eA-oBe"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="Radius">
<real key="value" value="12"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="bse-XL-ULx" secondAttribute="trailing" constant="15" id="FF5-XZ-24W"/>
<constraint firstItem="bse-XL-ULx" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="NzJ-lg-1J8"/>
<constraint firstAttribute="bottom" secondItem="bse-XL-ULx" secondAttribute="bottom" constant="12" id="XC0-MZ-dU8"/>
<constraint firstItem="bse-XL-ULx" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="15" id="hQ7-6k-S6M"/>
</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="EmailTimeL" destination="2zo-ld-bPP" id="8MG-Zd-qUK"/>
<outlet property="ListDot" destination="Fi7-Jr-Qip" id="NUJ-AK-DYk"/>
<outlet property="ListFirstL" destination="Lkh-fE-u5M" id="d3U-2d-SAM"/>
<outlet property="descpText" destination="8Mr-iL-2qm" id="HhE-NY-ozI"/>
<outlet property="descpText1" destination="S8d-tj-cjO" id="SJ7-ZV-MzU"/>
<outlet property="groupName" destination="49v-3u-EtJ" id="obF-nw-R09"/>
<outlet property="selectBtn" destination="XwR-Ch-R1t" id="lCd-A7-DrQ"/>
</connections>
<point key="canvasLocation" x="99.236641221374043" y="-11.619718309859156"/>
</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>
//
// 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 { ...@@ -39,6 +39,19 @@ class HomeInfoViewController:BaseViewController {
let sview:HomeInfoView = HomeInfoView(frame: CGRect(x: 0, y: cY, width: view.width, height: view.height - cY), ids: ids,type: self.type,titleText: titleText) let sview:HomeInfoView = HomeInfoView(frame: CGRect(x: 0, y: cY, width: view.width, height: view.height - cY), ids: ids,type: self.type,titleText: titleText)
sview.titleShowHideCallBack = {[weak self] isShow in
guard let self else {return}
if isShow && self.titleLabel.alpha == 0 {
UIView.animate(withDuration: 0.1) {
self.titleLabel.alpha = 1
}
}else if isShow == false && self.titleLabel.alpha == 1{
UIView.animate(withDuration: 0.1) {
self.titleLabel.alpha = 0
}
}
}
sview.callBack = {[weak self] isSeleted in sview.callBack = {[weak self] isSeleted in
guard let self else {return} guard let self else {return}
...@@ -275,6 +288,16 @@ class HomeInfoViewController:BaseViewController { ...@@ -275,6 +288,16 @@ class HomeInfoViewController:BaseViewController {
return label return label
}() }()
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = .systemFont(ofSize: 14, weight: .bold)
label.textColor = UIColor.colorWithHex(hexStr: black3Color)
label.text = titleText
label.alpha = 0
label.sizeToFit()
return label
}()
var ids: [[AssetModel]]? var ids: [[AssetModel]]?
var titleText : String? var titleText : String?
...@@ -373,6 +396,10 @@ class HomeInfoViewController:BaseViewController { ...@@ -373,6 +396,10 @@ class HomeInfoViewController:BaseViewController {
titleView.addSubview(seletedAllBtn) titleView.addSubview(seletedAllBtn)
titleLabel.x = titleView.backBtn.width + titleView.backBtn.x + 10
titleLabel.centerY = navCenterY
titleView.addSubview(titleLabel)
view.addSubview(tablewView) view.addSubview(tablewView)
view.addSubview(self.defaultImageView) view.addSubview(self.defaultImageView)
self.defaultImageView.snp.makeConstraints { make in self.defaultImageView.snp.makeConstraints { make in
......
...@@ -62,7 +62,14 @@ class HomeViewController:BaseViewController { ...@@ -62,7 +62,14 @@ class HomeViewController:BaseViewController {
case 3 : case 3 :
DispatchQueue.main.async {[weak self] in DispatchQueue.main.async {[weak self] in
guard let self else {return} guard let self else {return}
//FIXME: 是否登录了谷歌邮箱
if false {
let vc:EmailCleanController = EmailCleanController()
self.navigationController?.pushViewController(vc, animated: true)
}else{
let vc:EmailLoginController = EmailLoginController()
self.navigationController?.pushViewController(vc, animated: true)
}
} }
break break
case 4 : case 4 :
...@@ -142,9 +149,9 @@ class HomeViewController:BaseViewController { ...@@ -142,9 +149,9 @@ class HomeViewController:BaseViewController {
let homeSimilarImageResourceUpdate = Notification.Name("HomeSimilarImageResourceUpdate") let homeSimilarImageResourceUpdate = Notification.Name("HomeSimilarImageResourceUpdate")
NotificationCenter.default.addObserver(self, selector: #selector(handleHomeSimilarImageResourceUpdate(_:)), name: homeSimilarImageResourceUpdate, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleHomeSimilarImageResourceUpdate(_:)), name: homeSimilarImageResourceUpdate, object: nil)
homeView = HomeView(frame: view.bounds) homeView = HomeView(frame: view.bounds)
homeView?.y = cWindow?.safeAreaInsets.top ?? 20
homeView?.height = view.height - (cWindow?.safeAreaInsets.top ?? 20)
homeView?.titleCallBack = {[weak self] model,type in homeView?.titleCallBack = {[weak self] model,type in
guard let self else {return} guard let self else {return}
......
...@@ -32,25 +32,25 @@ class HomeCollectionViewHeader : UICollectionReusableView { ...@@ -32,25 +32,25 @@ class HomeCollectionViewHeader : UICollectionReusableView {
return view return view
}() }()
private lazy var tipLabel:UILabel = { // private lazy var tipLabel:UILabel = {
let label = UILabel() // let label = UILabel()
label.numberOfLines = 0 // 支持多行 // label.numberOfLines = 0 // 支持多行
return label // return label
}() // }()
private func setupUI() { private func setupUI() {
// 文本 // 文本
self.addSubview(self.tipLabel) // self.addSubview(self.tipLabel)
self.tipLabel.snp.makeConstraints { make in // self.tipLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(8) // make.left.equalToSuperview().offset(8)
make.top.equalToSuperview().offset(4) // make.top.equalToSuperview().offset(44)
make.height.equalTo(17) // make.height.equalTo(17)
} // }
self.addSubview(self.progressBar) self.addSubview(self.progressBar)
self.progressBar.snp.makeConstraints { make in self.progressBar.snp.makeConstraints { make in
make.top.equalTo(self.tipLabel.snp.bottom).offset(12) make.top.equalTo(self.snp.top).offset(12 + 44 + 17)
make.width.equalToSuperview().offset(-16) make.width.equalToSuperview().offset(-16)
make.height.equalTo(31) make.height.equalTo(31)
make.left.equalToSuperview().offset(8) make.left.equalToSuperview().offset(8)
...@@ -90,7 +90,7 @@ extension HomeCollectionViewHeader{ ...@@ -90,7 +90,7 @@ extension HomeCollectionViewHeader{
/// - Parameters: /// - Parameters:
/// - count: 文件数量 /// - count: 文件数量
/// - fileSize: 文件总大小 /// - fileSize: 文件总大小
func setFileAndCount(count:Int,fileSize:Double) { func setFileAndCount(count:Int,fileSize:Double) -> NSMutableAttributedString {
let countString = "\(count)" let countString = "\(count)"
let fileSizeString = formatFileSize(fileSize) let fileSizeString = formatFileSize(fileSize)
...@@ -122,9 +122,9 @@ extension HomeCollectionViewHeader{ ...@@ -122,9 +122,9 @@ extension HomeCollectionViewHeader{
.foregroundColor: UIColor.colorWithHex(hexStr: black6Color) .foregroundColor: UIColor.colorWithHex(hexStr: black6Color)
], range: nsRange2) ], range: nsRange2)
} }
return attributedText
// 将 attributedText 赋值给 UILabel // 将 attributedText 赋值给 UILabel
self.tipLabel.attributedText = attributedText // self.tipLabel.attributedText = attributedText
} }
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
import UIKit import UIKit
class HomeInfoView :UIView{ class HomeInfoView :UIView {
var ids:[[AssetModel]]? var ids:[[AssetModel]]?
...@@ -20,10 +20,11 @@ class HomeInfoView :UIView{ ...@@ -20,10 +20,11 @@ class HomeInfoView :UIView{
var callBack:callBack<Any> = {text in} var callBack:callBack<Any> = {text in}
var deleteCallBack:callBack<[AssetModel]> = {array in } var deleteCallBack:callBack<[AssetModel]> = {array in }
var titleShowHideCallBack:callBack<Bool> = {isShow in}
lazy var tableView:UITableView = { lazy var tableView:UITableView = {
let sview:UITableView = UITableView.init(frame: bounds) let sview:UITableView = UITableView(frame: bounds, style: .grouped) //UITableView.init(frame: bounds )
sview.backgroundColor = .clear sview.backgroundColor = .clear
sview.separatorStyle = .none sview.separatorStyle = .none
sview.showsVerticalScrollIndicator = false sview.showsVerticalScrollIndicator = false
...@@ -35,16 +36,13 @@ class HomeInfoView :UIView{ ...@@ -35,16 +36,13 @@ class HomeInfoView :UIView{
sview.sectionHeaderTopPadding = 0 sview.sectionHeaderTopPadding = 0
} }
return sview return sview
}() }()
lazy var headerView:HomeInfoTitleView = { lazy var headerView:HomeInfoTitleView = {
let sview:HomeInfoTitleView = HomeInfoTitleView(frame: CGRect(x: 0, y: 0, width: width, height: 84)) let sview:HomeInfoTitleView = HomeInfoTitleView(frame: CGRect(x: 0, y: 0, width: width, height: 84))
sview.titleLabel.text = self.titleText sview.titleLabel.text = self.titleText
tableView.addSubview(sview)
return sview return sview
}() }()
...@@ -164,6 +162,7 @@ class HomeInfoView :UIView{ ...@@ -164,6 +162,7 @@ class HomeInfoView :UIView{
for section in 0..<self.tableView.numberOfSections { for section in 0..<self.tableView.numberOfSections {
for item in 0..<self.tableView.numberOfRows(inSection: section) { for item in 0..<self.tableView.numberOfRows(inSection: section) {
if let cell = self.tableView.cellForRow(at: IndexPath(row: item, section: section)) as? HomeInfoTableViewCell { if let cell = self.tableView.cellForRow(at: IndexPath(row: item, section: section)) as? HomeInfoTableViewCell {
cell.checkSeletedAll()
UIView.transition(with: cell.collectionView!, duration: 0.3, options: .transitionCrossDissolve, animations: { UIView.transition(with: cell.collectionView!, duration: 0.3, options: .transitionCrossDissolve, animations: {
cell.collectionView?.reloadData() cell.collectionView?.reloadData()
}, completion: nil) }, completion: nil)
...@@ -182,7 +181,6 @@ class HomeInfoView :UIView{ ...@@ -182,7 +181,6 @@ class HomeInfoView :UIView{
} }
} }
} }
return selectedArray return selectedArray
} }
...@@ -255,6 +253,20 @@ class HomeInfoView :UIView{ ...@@ -255,6 +253,20 @@ class HomeInfoView :UIView{
extension HomeInfoView:UITableViewDataSource,UITableViewDelegate { extension HomeInfoView:UITableViewDataSource,UITableViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let OffsetY = scrollView.contentOffset.y
let top = CGRectGetMaxY(self.headerView.titleLabel.frame) + 8
var orgy = OffsetY - top
if orgy < 0 {
orgy = 0
}
titleShowHideCallBack( OffsetY > top )
var farme = self.headerView.frame
farme.origin.y = orgy
self.headerView.frame = farme
tableView.bringSubviewToFront(self.headerView)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ids?.count ?? 0 return ids?.count ?? 0
...@@ -284,13 +296,11 @@ extension HomeInfoView:UITableViewDataSource,UITableViewDelegate { ...@@ -284,13 +296,11 @@ extension HomeInfoView:UITableViewDataSource,UITableViewDelegate {
} }
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return headerView.height return headerView.height
} }
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return UIView()
return headerView
} }
} }
......
...@@ -9,7 +9,7 @@ import UIKit ...@@ -9,7 +9,7 @@ import UIKit
class HomeNavView:UIView { class HomeNavView:UIView {
private var settingBtn:UIButton! // private var settingBtn:UIButton!
private var proBtn:UIButton! private var proBtn:UIButton!
private lazy var homeTitle : UILabel = { private lazy var homeTitle : UILabel = {
let label = UILabel() let label = UILabel()
...@@ -38,24 +38,22 @@ class HomeNavView:UIView { ...@@ -38,24 +38,22 @@ class HomeNavView:UIView {
self.addSubview(self.homeTitle) self.addSubview(self.homeTitle)
self.homeTitle.snp.makeConstraints { make in self.homeTitle.snp.makeConstraints { make in
make.left.equalTo(15 + 8) make.left.equalTo(15 + 8)
make.top.equalTo(8 + statusBarHeight) make.top.equalTo(8)
make.height.equalTo(28) make.height.equalTo(28)
make.width.equalTo(149) make.width.equalTo(149)
} }
// 设置按钮 // 设置按钮
self.settingBtn = UIButton() // self.settingBtn = UIButton()
self.settingBtn.setImage(UIImage(named: "ic_setting_com"), for: .normal) // self.settingBtn.setImage(UIImage(named: "ic_setting_com"), for: .normal)
self.settingBtn.addTarget(self, action: #selector(settingBtnClick), for: .touchUpInside) // self.settingBtn.addTarget(self, action: #selector(settingBtnClick), for: .touchUpInside)
self.addSubview(settingBtn) // self.addSubview(settingBtn)
self.settingBtn.snp.makeConstraints { make in // self.settingBtn.snp.makeConstraints { make in
make.centerY.equalTo(self.homeTitle.snp.centerY) // make.centerY.equalTo(self.homeTitle.snp.centerY)
make.right.equalTo(-marginLR) // make.right.equalTo(-marginLR)
make.width.height.equalTo(iconWH) // make.width.height.equalTo(iconWH)
//
} // }
// 会员按钮 // 会员按钮
self.proBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 70, height: iconWH)) self.proBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 70, height: iconWH))
self.proBtn.setBackgroundImage(UIImage(named: "ic_pro_home"), for: .normal) self.proBtn.setBackgroundImage(UIImage(named: "ic_pro_home"), for: .normal)
...@@ -63,7 +61,7 @@ class HomeNavView:UIView { ...@@ -63,7 +61,7 @@ class HomeNavView:UIView {
self.addSubview(proBtn) self.addSubview(proBtn)
self.proBtn.snp.makeConstraints { make in self.proBtn.snp.makeConstraints { make in
make.centerY.equalTo(self.homeTitle.snp.centerY) make.centerY.equalTo(self.homeTitle.snp.centerY)
make.right.equalTo(self.settingBtn.snp.left).offset(-8) make.right.equalTo(self.snp.right).offset(-8-iconWH-marginLR)
make.width.equalTo(78) make.width.equalTo(78)
make.height.equalTo(iconWH) make.height.equalTo(iconWH)
} }
...@@ -73,11 +71,12 @@ class HomeNavView:UIView { ...@@ -73,11 +71,12 @@ class HomeNavView:UIView {
extension HomeNavView { extension HomeNavView {
@objc private func settingBtnClick() { // @objc private func settingBtnClick() {
let homeNavViewModel = HomeNavViewModel() // let homeNavViewModel = HomeNavViewModel()
let settingViewController = SettingViewController() // let settingViewController = SettingViewController()
homeNavViewModel.pushToDetailController(currentView: self, destnationController: settingViewController) // homeNavViewModel.pushToDetailController(currentView: self, destnationController: settingViewController)
} // }
@objc private func proBtnClick() { @objc private func proBtnClick() {
if IAPManager.share.isSubscribed == false { if IAPManager.share.isSubscribed == false {
HomePayViewController.show {} HomePayViewController.show {}
......
...@@ -11,6 +11,7 @@ import SnapKit ...@@ -11,6 +11,7 @@ import SnapKit
class HomeView:UIView { class HomeView:UIView {
private var homeTabbarView:HomeTabbarView? private var homeTabbarView:HomeTabbarView?
private var settingBtn:UIButton!
private var homeNavView:HomeNavView? private var homeNavView:HomeNavView?
...@@ -30,6 +31,17 @@ class HomeView:UIView { ...@@ -30,6 +31,17 @@ class HomeView:UIView {
var model:PhotosManagerModel? var model:PhotosManagerModel?
var isScroll = false {
didSet {
if isScroll {
DispatchQueue.main.async {
self.tipLabel.attributedText = self.attribet
}
}
}
}
var attribet:NSAttributedString?
lazy var collectionView:UICollectionView = { lazy var collectionView:UICollectionView = {
let cY:CGFloat = 16.RW() let cY:CGFloat = 16.RW()
...@@ -51,11 +63,19 @@ class HomeView:UIView { ...@@ -51,11 +63,19 @@ class HomeView:UIView {
if #available(iOS 11.0, *) { if #available(iOS 11.0, *) {
sview.contentInsetAdjustmentBehavior = .never sview.contentInsetAdjustmentBehavior = .never
} }
sview.clipsToBounds = true
sview.backgroundColor = .clear sview.backgroundColor = .clear
return sview return sview
}() }()
private lazy var topNaviView: UIView = {
let backView = UIView()
backView.backgroundColor = UIColor(hex: "#DAEAFF")
addSubview(backView)
return backView
}()
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
...@@ -68,20 +88,21 @@ class HomeView:UIView { ...@@ -68,20 +88,21 @@ class HomeView:UIView {
} }
func setTitle() { func setTitle() {
self.attribet = self.homeHeader?.setFileAndCount(count: model?.allFileNumber ?? 0, fileSize: model?.allFileSize ?? 0)
DispatchQueue.main.async {[weak self] in DispatchQueue.main.async {[weak self] in
guard let self else {return} guard let self else {return}
if isScroll == false {
self.homeHeader?.setFileAndCount(count: model?.allFileNumber ?? 0, fileSize: model?.allFileSize ?? 0) self.tipLabel.attributedText = self.attribet
self.homeHeader?.setNeedsLayout() self.homeHeader?.setNeedsLayout()
self.homeHeader?.layoutIfNeeded() self.homeHeader?.layoutIfNeeded()
}
} }
} }
private func setupUI() { private func setupUI() {
backgroundColor = .clear backgroundColor = .clear
clipsToBounds = true
homeTabbarView = HomeTabbarView(frame: CGRect(x: 0, y: 0, width: self.width, height: safeHeight + 66)) homeTabbarView = HomeTabbarView(frame: CGRect(x: 0, y: 0, width: self.width, height: safeHeight + 66))
...@@ -102,14 +123,29 @@ class HomeView:UIView { ...@@ -102,14 +123,29 @@ class HomeView:UIView {
homeNavView = HomeNavView(frame: CGRect(x: 0, y: 0, width: width, height: statusBarHeight + 44)) homeNavView = HomeNavView(frame: CGRect(x: 0, y: 0, width: width, height: statusBarHeight + 44))
topNaviView.snp.makeConstraints { make in
make.top.centerX.width.equalToSuperview()
make.height.equalTo(44)
}
self.addSubview(homeNavView!) self.addSubview(homeNavView!)
homeNavView?.snp.makeConstraints({ make in homeNavView?.snp.makeConstraints({ make in
make.top.centerX.width.equalToSuperview() make.top.centerX.width.equalToSuperview()
make.height.equalTo(statusBarHeight + 44) make.height.equalTo(44)
}) })
self.settingBtn = UIButton()
self.settingBtn.setImage(UIImage(named: "ic_setting_com"), for: .normal)
self.settingBtn.addTarget(self, action: #selector(settingBtnClick), for: .touchUpInside)
self.addSubview(settingBtn)
self.settingBtn.snp.makeConstraints { make in
make.centerY.equalTo(self.homeNavView!.snp.centerY)
make.right.equalTo(-marginLR)
make.width.height.equalTo(iconWH)
}
bottomView = UIView(frame: CGRect(x: 0, y: 0, width: width, height: safeHeight + 10)) bottomView = UIView(frame: CGRect(x: 0, y: 0, width: width, height: safeHeight + 10))
bottomView?.backgroundColor = .white bottomView?.backgroundColor = .white
self.addSubview(bottomView!) self.addSubview(bottomView!)
...@@ -118,15 +154,19 @@ class HomeView:UIView { ...@@ -118,15 +154,19 @@ class HomeView:UIView {
make.bottom.equalToSuperview().offset(10) make.bottom.equalToSuperview().offset(10)
make.height.equalTo(safeHeight + 10) make.height.equalTo(safeHeight + 10)
}) })
self.insertSubview(collectionView, at: 0) self.insertSubview(collectionView, at: 0)
collectionView.snp.makeConstraints { make in collectionView.snp.makeConstraints { make in
make.top.equalTo(self.homeNavView!.snp.bottom).offset(0) make.top.centerX.equalToSuperview()
make.centerX.equalToSuperview()
make.width.equalToSuperview().offset(-2 * marginLR) make.width.equalToSuperview().offset(-2 * marginLR)
make.bottom.equalToSuperview().offset( -homeTabbarView!.height - 16) make.bottom.equalToSuperview().offset( -homeTabbarView!.height - 16)
} }
self.addSubview(self.tipLabel)
self.tipLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(8+marginLR)
make.top.equalTo(self.collectionView.snp.top).offset(44)
make.height.equalTo(17)
}
} }
func etCell(indexPath: IndexPath) -> UICollectionViewCell { func etCell(indexPath: IndexPath) -> UICollectionViewCell {
...@@ -134,10 +174,53 @@ class HomeView:UIView { ...@@ -134,10 +174,53 @@ class HomeView:UIView {
return UICollectionViewCell() return UICollectionViewCell()
} }
private lazy var tipLabel:UILabel = {
let label = UILabel()
label.numberOfLines = 0 // 支持多行
return label
}()
} }
extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICollectionViewDelegate { extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICollectionViewDelegate {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
isScroll = true
}
func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
isScroll = true
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
var changeY = offsetY
if changeY < 0 {
changeY = 0
}
var cframe = self.homeNavView?.frame
cframe?.origin.y = -changeY
self.homeNavView?.frame = cframe ?? CGRect()
var centerY = 22 + iconWH - offsetY
let setCenterY = settingBtn.center.y
if centerY < setCenterY {
centerY = setCenterY
}
tipLabel.centerY = centerY
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if !decelerate {
isScroll = false // 拖动停止且无需减速
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
isScroll = false // 减速完全停止
}
func numberOfSections(in collectionView: UICollectionView) -> Int { func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2 return 2
...@@ -322,7 +405,7 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol ...@@ -322,7 +405,7 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
func referenceSizeForHeader(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGSize { func referenceSizeForHeader(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGSize {
if section == 0 { if section == 0 {
if Singleton.shared.photoPermission == .authorized { if Singleton.shared.photoPermission == .authorized {
return CGSize(width: self.collectionView.width, height: 76) return CGSize(width: self.collectionView.width, height: 76 + (self.homeNavView?.height ?? 0))
}else{ }else{
return CGSize(width: self.collectionView.width, height: 404) return CGSize(width: self.collectionView.width, height: 404)
} }
...@@ -334,4 +417,12 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol ...@@ -334,4 +417,12 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
let indexPath = IndexPath(item: 0, section: 0) let indexPath = IndexPath(item: 0, section: 0)
return self.collectionView.supplementaryView(forElementKind: UICollectionView.elementKindSectionHeader, at: indexPath) return self.collectionView.supplementaryView(forElementKind: UICollectionView.elementKindSectionHeader, at: indexPath)
} }
@objc private func settingBtnClick() {
let homeNavViewModel = HomeNavViewModel()
let settingViewController = SettingViewController()
homeNavViewModel.pushToDetailController(currentView: self, destnationController: settingViewController)
}
} }
...@@ -72,10 +72,21 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -72,10 +72,21 @@ class HomeOtherCollectionCell: UICollectionViewCell {
return iv return iv
}() }()
lazy var playerView: SecretVideoPlayer = {
let play = SecretVideoPlayer()
play.isUserInteractionEnabled = false
play.fromState = .home
play.Radius = 16
play.contentMode = .scaleAspectFill
play.isLooping = true
return play
}()
// MARK: - Lifecycle // MARK: - Lifecycle
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
setupUI() setupUI()
NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: Notification.Name("applicationDidBecomeActive"), object: nil)
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
...@@ -87,16 +98,20 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -87,16 +98,20 @@ class HomeOtherCollectionCell: UICollectionViewCell {
backgroundColor = .white backgroundColor = .white
self.contentView.addSubview(self.titleLabel) self.contentView.addSubview(self.titleLabel)
self.contentView.addSubview(self.imageView) self.contentView.addSubview(self.imageView)
self.contentView.addSubview(self.playImageView) self.contentView.addSubview(self.playerView)
// self.contentView.addSubview(self.playImageView)
self.imageView.addSubview(self.infoBackView) self.playerView.addSubview(self.infoBackView)
self.infoBackView.addSubview(self.countLabel) self.infoBackView.addSubview(self.countLabel)
self.infoBackView.addSubview(self.sizeLabel) self.infoBackView.addSubview(self.sizeLabel)
self.infoBackView.addSubview(self.moreImageView) self.infoBackView.addSubview(self.moreImageView)
} }
@objc private func didBecomeActive() -> Void {
self.playerView.resume()
}
var model:HomePhotosModel? { var model:HomePhotosModel? {
didSet { didSet {
...@@ -161,19 +176,35 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -161,19 +176,35 @@ class HomeOtherCollectionCell: UICollectionViewCell {
// 从 PHAsset 获取 AVAsset // 从 PHAsset 获取 AVAsset
if let videoAsset = PhotoAndVideoMananger.mananger.getPHAsssetwithID(ids: [asset.localIdentifier]){ if let videoAsset = PhotoAndVideoMananger.mananger.getPHAsssetwithID(ids: [asset.localIdentifier]){
// 使用requestImageForAsset方法请求视频的第一帧图片 // 使用requestImageForAsset方法请求视频的第一帧图片
PHImageManager.default().requestImage(for: videoAsset, targetSize: CGSize(width: 400, height: 400), contentMode: PHImageContentMode.aspectFit, options: options) { image, _ in
// 处理获取到的图片 let options = PHVideoRequestOptions()
if let thumbnailImage = image { options.version = .current
// 使用获取到的图片,例如显示在UIImageView上 options.deliveryMode = .automatic // 根据需求调整视频质量:ml-citation{ref="2,7" data="citationList"}
DispatchQueue.main.async {
// 确保在主线程更新UI PHImageManager.default().requestAVAsset(
self.imageView.image = thumbnailImage forVideo: videoAsset,
} options: options
} else { ) { (avAsset, audioMix, info) in
self.imageView.image = UIImage(named: "img_vedio_defpage") guard let avAsset = avAsset as? AVURLAsset else { return }
print("无法获取图片") let videoURL = avAsset.url
} print("视频地址: \(videoURL)")
} DispatchQueue.main.async {
self.playerView.playVideo(from: videoURL)
}
}
// PHImageManager.default().requestImage(for: videoAsset, targetSize: CGSize(width: 400, height: 400), contentMode: PHImageContentMode.aspectFit, options: options) { image, _ in
// // 处理获取到的图片
// if let thumbnailImage = image {
// // 使用获取到的图片,例如显示在UIImageView上
// DispatchQueue.main.async {
// // 确保在主线程更新UI
// self.imageView.image = thumbnailImage
// }
// } else {
// self.imageView.image = UIImage(named: "img_vedio_defpage")
// print("无法获取图片")
// }
// }
} }
} }
} }
...@@ -206,14 +237,16 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -206,14 +237,16 @@ class HomeOtherCollectionCell: UICollectionViewCell {
make.height.equalTo(self.width - 32) make.height.equalTo(self.width - 32)
} }
self.infoBackView.snp.makeConstraints { make in self.infoBackView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview() make.left.right.bottom.equalToSuperview()
make.height.equalTo(40) make.height.equalTo(40)
} }
self.playImageView.snp.makeConstraints { make in // self.playImageView.snp.makeConstraints { make in
make.width.height.equalTo(43) // make.width.height.equalTo(43)
make.center.equalTo(self.imageView.snp.center) // make.center.equalTo(self.imageView.snp.center)
// }
self.playerView.snp.makeConstraints { make in
make.left.right.top.bottom.equalTo(imageView)
} }
titleLabel.snp.makeConstraints { make in titleLabel.snp.makeConstraints { make in
...@@ -237,7 +270,10 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -237,7 +270,10 @@ class HomeOtherCollectionCell: UICollectionViewCell {
make.right.equalToSuperview().offset(-12) make.right.equalToSuperview().offset(-12)
make.centerY.equalToSuperview() make.centerY.equalToSuperview()
} }
// titleLabel.sizeToFit()
} }
deinit {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name("applicationDidBecomeActive"), object: nil)
}
} }
...@@ -54,7 +54,7 @@ class ImageCollectionCell:UICollectionViewCell { ...@@ -54,7 +54,7 @@ class ImageCollectionCell:UICollectionViewCell {
backImageView = UIImageView() backImageView = UIImageView()
backImageView?.isUserInteractionEnabled = true backImageView?.isUserInteractionEnabled = true
backImageView?.contentMode = .scaleAspectFit backImageView?.contentMode = .scaleAspectFill
backImageView?.clipsToBounds = true backImageView?.clipsToBounds = true
backImageView?.layer.masksToBounds = true backImageView?.layer.masksToBounds = true
backImageView?.isUserInteractionEnabled = true backImageView?.isUserInteractionEnabled = true
......
...@@ -26,7 +26,6 @@ class HomePayModel: NSObject ,SKProductsRequestDelegate ,SKPaymentTransactionObs ...@@ -26,7 +26,6 @@ class HomePayModel: NSObject ,SKProductsRequestDelegate ,SKPaymentTransactionObs
private let productIdentifiers:[String] = ["com.app.phonemanager.week.member" , "com.app.phonemanager.lifetime.member"] private let productIdentifiers:[String] = ["com.app.phonemanager.week.member" , "com.app.phonemanager.lifetime.member"]
var isSubscribed:Bool = false var isSubscribed:Bool = false
var isNoAd:Bool { var isNoAd:Bool {
get { get {
......
...@@ -11,40 +11,62 @@ let PMShowImgCellID = "PMShowImgCell" ...@@ -11,40 +11,62 @@ let PMShowImgCellID = "PMShowImgCell"
class PMShowImgCell: UICollectionViewCell { class PMShowImgCell: UICollectionViewCell {
var callblock:(()->Void) = {}
@objc private func selectTap() -> Void {
callblock()
}
var icon:UIImage = UIImage() { var icon:UIImage = UIImage() {
didSet { didSet {
iconView.image = icon scaleImg.icon = icon
var size = icon.size // iconView.image = icon
if size.width != 0 && size.height != 0 { // var size = icon.size
if size.height < size.width { // if size.width != 0 && size.height != 0 {
let width = self.width // if size.height < size.width {
size = CGSize(width: width, height: size.height * (width/size.width) ) // let width = self.width
}else{ // size = CGSize(width: width, height: size.height * (width/size.width) )
let width = self.width // }else{
let height = size.height * (width/size.width) // let width = self.width
if height > self.height { // let height = size.height * (width/size.width)
size = CGSize(width: width * (self.height/height), height: height ) // if height > self.height {
}else { // size = CGSize(width: width * (self.height/height), height: height )
size = CGSize(width: width, height: height ) // }else {
} // size = CGSize(width: width, height: height )
} // }
} // }
// }
iconView.snp.remakeConstraints { make in //
make.centerX.centerY.equalToSuperview() // iconView.snp.remakeConstraints { make in
make.size.equalTo(size) // make.centerX.centerY.equalToSuperview()
} // make.size.equalTo(size)
// }
} }
} }
private lazy var iconView: UIImageView = { private lazy var iconView: UIImageView = {
let info = UIImageView() let info = UIImageView()
info.contentMode = .scaleToFill info.contentMode = .scaleAspectFill
contentView.addSubview(info) contentView.addSubview(info)
info.clipsToBounds = true info.clipsToBounds = true
return info return info
}() }()
lazy var selectBtn: UIButton = {
let select = UIButton(type: .custom)
select.setImage(UIImage(named: ""), for: .normal)
select.setImage(UIImage(named: ""), for: .selected)
select.addTarget(self, action: #selector(selectTap), for: .touchUpInside)
contentView.addSubview(select)
return select
}()
private lazy var scaleImg: PMScaleImageView = {
let img = PMScaleImageView()
contentView.addSubview(img)
return img
}()
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
setup() setup()
...@@ -59,5 +81,13 @@ class PMShowImgCell: UICollectionViewCell { ...@@ -59,5 +81,13 @@ class PMShowImgCell: UICollectionViewCell {
iconView.snp.makeConstraints { make in iconView.snp.makeConstraints { make in
make.left.right.bottom.top.equalToSuperview() make.left.right.bottom.top.equalToSuperview()
} }
scaleImg.snp.makeConstraints { make in
make.left.right.bottom.top.equalToSuperview()
}
selectBtn.snp.makeConstraints { make in
make.right.equalToSuperview()
make.width.height.equalTo(iconWH)
make.bottom.equalToSuperview().offset(-10)
}
} }
} }
...@@ -11,7 +11,7 @@ import UIKit ...@@ -11,7 +11,7 @@ import UIKit
let PMShowItemCellID = "PMShowItemCell" let PMShowItemCellID = "PMShowItemCell"
class PMShowItemCell: UICollectionViewCell { class PMShowItemCell: UICollectionViewCell {
var isCurrent:Bool = false { var isCurrent:Bool = false {
didSet { didSet {
if isCurrent { if isCurrent {
...@@ -37,6 +37,15 @@ class PMShowItemCell: UICollectionViewCell { ...@@ -37,6 +37,15 @@ class PMShowItemCell: UICollectionViewCell {
return ic return ic
}() }()
private lazy var selectBtn: UIButton = {
let select = UIButton(type: .custom)
select.setImage(UIImage(named: ""), for: .normal)
select.setImage(UIImage(named: ""), for: .selected)
contentView.addSubview(select)
select.isUserInteractionEnabled = false
return select
}()
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
clipsToBounds = true clipsToBounds = true
...@@ -52,6 +61,11 @@ class PMShowItemCell: UICollectionViewCell { ...@@ -52,6 +61,11 @@ class PMShowItemCell: UICollectionViewCell {
iconV.snp.makeConstraints { make in iconV.snp.makeConstraints { make in
make.left.right.top.bottom.equalToSuperview() make.left.right.top.bottom.equalToSuperview()
} }
selectBtn.snp.makeConstraints { make in
make.right.equalToSuperview()
make.width.height.equalTo(iconWH)
make.bottom.equalToSuperview()
}
} }
} }
...@@ -29,6 +29,7 @@ class PMShowImgVideoController: BaseViewController { ...@@ -29,6 +29,7 @@ class PMShowImgVideoController: BaseViewController {
var homeDataSource : [ImageSeletedCollectionItem]? var homeDataSource : [ImageSeletedCollectionItem]?
var currentIdx = 0 var currentIdx = 0
var selectSet = NSMutableSet()
var url : URL? var url : URL?
...@@ -40,13 +41,13 @@ class PMShowImgVideoController: BaseViewController { ...@@ -40,13 +41,13 @@ class PMShowImgVideoController: BaseViewController {
super.viewWillAppear(animated) super.viewWillAppear(animated)
self.MaxCollection.snp.makeConstraints { make in self.MaxCollection.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(20) make.left.right.equalToSuperview().inset(20)
make.top.top.equalTo(titleView.snp.bottom).offset(20) make.top.equalTo(titleView.snp.bottom).offset(20)
make.bottom.equalToSuperview().inset(100) make.bottom.equalToSuperview().inset(100 + (cWindow?.safeAreaInsets.bottom ?? 0))
} }
self.bottItems.snp.makeConstraints { make in self.bottItems.snp.makeConstraints { make in
make.left.right.equalToSuperview() make.left.right.equalTo(MaxCollection)
make.top.equalTo(MaxCollection.snp.bottom) make.top.equalTo(MaxCollection.snp.bottom)
make.bottom.equalToSuperview() make.bottom.equalToSuperview().offset(-(cWindow?.safeAreaInsets.bottom ?? 0))
} }
self.view.layoutIfNeeded() self.view.layoutIfNeeded()
self.MaxCollection.scrollToItem(at: IndexPath(row: currentIdx, section: 0), at: .centeredHorizontally, animated: false) self.MaxCollection.scrollToItem(at: IndexPath(row: currentIdx, section: 0), at: .centeredHorizontally, animated: false)
...@@ -71,19 +72,20 @@ class PMShowImgVideoController: BaseViewController { ...@@ -71,19 +72,20 @@ class PMShowImgVideoController: BaseViewController {
private lazy var bottItems: UICollectionView = { private lazy var bottItems: UICollectionView = {
let flowlayout = UICollectionViewFlowLayout() let flowlayout = UICollectionViewFlowLayout()
flowlayout.sectionInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20) flowlayout.sectionInset = UIEdgeInsets()
flowlayout.minimumInteritemSpacing = 0 flowlayout.minimumInteritemSpacing = 10
flowlayout.minimumLineSpacing = 10 flowlayout.minimumLineSpacing = 10
flowlayout.scrollDirection = .horizontal flowlayout.scrollDirection = .horizontal
let col = UICollectionView(frame: CGRect(), collectionViewLayout: flowlayout) let col = UICollectionView(frame: CGRect(), collectionViewLayout: flowlayout)
col.delegate = self; col.delegate = self;
col.dataSource = self; col.dataSource = self;
col.register(PMShowItemCell.self, forCellWithReuseIdentifier: PMShowItemCellID) col.register(PMShowItemCell.self, forCellWithReuseIdentifier: PMShowItemCellID)
col.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "UICollectionViewCell")
col.showsHorizontalScrollIndicator = false col.showsHorizontalScrollIndicator = false
col.isPagingEnabled = true
view.addSubview(col) view.addSubview(col)
return col return col
}() }()
} }
extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{
...@@ -94,29 +96,52 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa ...@@ -94,29 +96,52 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
let offsetx = MaxCollection.contentOffset.x let offsetx = MaxCollection.contentOffset.x
let width = collectView.width let width = collectView.width
let current:Int = Int(offsetx / width) let current:Int = Int(offsetx / width)
currentIdx = current // currentIdx = current
bottItems.scrollToItem(at: IndexPath(row: current, section: 0), at: .left, animated: true)
}
}
private func setMaxCollection(collectionView:UICollectionView) -> Void {
if collectionView == bottItems {
let offsetX = collectionView.contentOffset.x
let idx = round(offsetX / (68 + 10))
UIView.animate(withDuration: 0.5) {
collectionView.contentOffset = CGPointMake( idx * (68 + 10) , 0)
}
MaxCollection.scrollToItem(at: IndexPath(row: Int(idx), section: 0), at: .centeredHorizontally, animated: true)
} }
} }
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
Print("1")
guard let collectView = scrollView as? UICollectionView else { return } guard let collectView = scrollView as? UICollectionView else { return }
if collectView == MaxCollection { // if collectView == MaxCollection {
bottItems.reloadData() // bottItems.reloadData()
} // }
self.setMaxCollection(collectionView: collectView)
} }
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
Print("2") if !decelerate {
guard let collectView = scrollView as? UICollectionView else { return }
self.setMaxCollection(collectionView: collectView)
}
} }
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == bottItems { if collectionView == bottItems {
if currentIdx != indexPath.row { if selectSet.contains(indexPath.row) {
currentIdx = indexPath.row selectSet.remove(indexPath.row)
MaxCollection.scrollToItem(at: indexPath, at: .left, animated: false) }else{
collectionView.reloadData() selectSet.add(indexPath.row)
} }
self.MaxCollection.reloadData()
collectionView.reloadData()
// if currentIdx != indexPath.row {
// currentIdx = indexPath.row
// MaxCollection.scrollToItem(at: indexPath, at: .left, animated: false)
// collectionView.reloadData()
// }
} }
} }
...@@ -124,7 +149,11 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa ...@@ -124,7 +149,11 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
if self.state == .secret { if self.state == .secret {
return imageVideoPath.count return imageVideoPath.count
}else { }else {
return self.homeDataSource?.count ?? 0 if collectionView == MaxCollection{
return self.homeDataSource?.count ?? 0
}else{
return (self.homeDataSource?.count ?? 0) + 1
}
} }
} }
...@@ -172,12 +201,25 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa ...@@ -172,12 +201,25 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
if collectionView == MaxCollection { if collectionView == MaxCollection {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowImgCellID, for: indexPath) as! PMShowImgCell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowImgCellID, for: indexPath) as! PMShowImgCell
cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage() cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage()
cell.isSelected = selectSet.contains(indexPath.row)
cell.callblock = {[weak self] in
guard let self = self else { return }
if self.selectSet.contains(indexPath.row){
self.selectSet.remove(indexPath.row)
}else{
self.selectSet.add(indexPath.row)
}
self.MaxCollection.reloadData()
self.bottItems.reloadData()
}
return cell return cell
}else { }else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell if indexPath.row < self.homeDataSource?.count ?? 0 {
cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage() let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell
cell.isCurrent = (self.currentIdx == indexPath.row) cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage()
return cell cell.isCurrent = selectSet.contains(indexPath.row) //(self.currentIdx == indexPath.row)
return cell
}
} }
} }
...@@ -201,13 +243,15 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa ...@@ -201,13 +243,15 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
cell.type = 1 cell.type = 1
return cell return cell
}else{ }else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell if indexPath.row < self.homeDataSource?.count ?? 0 {
cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage() let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell
cell.isCurrent = (self.currentIdx == indexPath.row) cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage()
return cell cell.isCurrent = (self.currentIdx == indexPath.row)
return cell
}
} }
} }
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "", for: indexPath) let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "UICollectionViewCell", for: indexPath)
return cell return cell
} }
...@@ -215,11 +259,13 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa ...@@ -215,11 +259,13 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
if collectionView == MaxCollection { if collectionView == MaxCollection {
return collectionView.size return collectionView.size
} }
return CGSize(width: 68, height: 68) if indexPath.row < self.homeDataSource?.count ?? 0 {
return CGSize(width: 68, height: 68)
}
return CGSize(width: collectionView.width - 68, height: 68)
} }
/// 根据LocalIdentifier获取视频的URL /// 根据LocalIdentifier获取视频的URL
/// - Parameters: /// - Parameters:
/// - localIdentifier: 资源标识 /// - localIdentifier: 资源标识
......
...@@ -14,6 +14,11 @@ class SecretVideoPlayer: UIView { ...@@ -14,6 +14,11 @@ class SecretVideoPlayer: UIView {
private var player: AVPlayer? private var player: AVPlayer?
var isLooping = false var isLooping = false
enum PlayerFrom {
case home
case other
}
enum playState { enum playState {
case start case start
case playing case playing
...@@ -21,6 +26,8 @@ class SecretVideoPlayer: UIView { ...@@ -21,6 +26,8 @@ class SecretVideoPlayer: UIView {
case end case end
} }
var fromState:PlayerFrom = .other
var state:playState = .start var state:playState = .start
override init(frame: CGRect) { override init(frame: CGRect) {
...@@ -49,8 +56,11 @@ class SecretVideoPlayer: UIView { ...@@ -49,8 +56,11 @@ class SecretVideoPlayer: UIView {
} }
private func setupPlayerLayer() { private func setupPlayerLayer() {
backgroundColor = .clear
let playerLayer = AVPlayerLayer() let playerLayer = AVPlayerLayer()
playerLayer.videoGravity = .resizeAspect playerLayer.backgroundColor = UIColor.clear.cgColor
playerLayer.shouldRasterize = true
playerLayer.rasterizationScale = UIScreen.main.scale
layer.addSublayer(playerLayer) layer.addSublayer(playerLayer)
let tap = UITapGestureRecognizer(target: self, action: #selector(tapClick)) let tap = UITapGestureRecognizer(target: self, action: #selector(tapClick))
self.addGestureRecognizer(tap) self.addGestureRecognizer(tap)
...@@ -60,6 +70,7 @@ class SecretVideoPlayer: UIView { ...@@ -60,6 +70,7 @@ class SecretVideoPlayer: UIView {
super.layoutSubviews() super.layoutSubviews()
if let playerLayer = layer.sublayers?.first as? AVPlayerLayer { if let playerLayer = layer.sublayers?.first as? AVPlayerLayer {
playerLayer.frame = bounds playerLayer.frame = bounds
} }
} }
...@@ -71,6 +82,12 @@ class SecretVideoPlayer: UIView { ...@@ -71,6 +82,12 @@ class SecretVideoPlayer: UIView {
player = AVPlayer(url: url!) player = AVPlayer(url: url!)
if let playerLayer = layer.sublayers?.first as? AVPlayerLayer { if let playerLayer = layer.sublayers?.first as? AVPlayerLayer {
playerLayer.player = player playerLayer.player = player
if fromState == .home {
playerLayer.videoGravity = .resizeAspectFill
player?.isMuted = true
}else{
playerLayer.videoGravity = .resizeAspect
}
} }
NotificationCenter.default.addObserver( NotificationCenter.default.addObserver(
self, self,
...@@ -79,6 +96,7 @@ class SecretVideoPlayer: UIView { ...@@ -79,6 +96,7 @@ class SecretVideoPlayer: UIView {
object: player?.currentItem object: player?.currentItem
) )
state = .playing state = .playing
player?.play() player?.play()
} }
......
...@@ -20,6 +20,18 @@ class WidgetPublicModel: NSObject { ...@@ -20,6 +20,18 @@ class WidgetPublicModel: NSObject {
return batt return batt
} }
public class func BatteryState() -> Bool {
let device = UIDevice.current
device.isBatteryMonitoringEnabled = true
switch device.batteryState {
case .charging:
return true
default:
return false
}
}
/// 已使用 /// 已使用
/// - Returns: 已使用空间 /// - Returns: 已使用空间
...@@ -68,6 +80,10 @@ class WidgetPublicModel: NSObject { ...@@ -68,6 +80,10 @@ class WidgetPublicModel: NSObject {
return val return val
} }
class func isLowPowerModeEnabled() -> Bool {
return ProcessInfo.processInfo.isLowPowerModeEnabled
}
} }
class widgetAppgourp: NSObject { class widgetAppgourp: NSObject {
...@@ -75,7 +91,12 @@ class widgetAppgourp: NSObject { ...@@ -75,7 +91,12 @@ class widgetAppgourp: NSObject {
static let share = widgetAppgourp() static let share = widgetAppgourp()
func PushWidgetData(_ widget:Int = 0 , battery:Int , storage:Int ) -> Void { func PushWidgetData(_ widget:Int = 0 , battery:Int , storage:Int ) -> Void {
let data = WidgetData(userId: "", widget: widget, battery: battery, widgetStorage: storage)
let disk = WidgetPublicModel.getDiskSpace()
let allInt = Int(CGFloat(disk.0)/(1000.0 * 1000.0 * 1000.0))
let useInt = Int(CGFloat(disk.0 - disk.1)/(1000.0 * 1000.0 * 1000.0))
let state = (WidgetPublicModel.isLowPowerModeEnabled() ? "On" : "Off")
let data = WidgetData(userId: "", widget: widget, battery: battery, widgetStorage: storage,AllSpace: allInt , UseSpace: useInt ,batteryState:state ,isCharging: WidgetPublicModel.BatteryState())
if let sharedDefaults = UserDefaults(suiteName: "group.com.app.phonemanager") { if let sharedDefaults = UserDefaults(suiteName: "group.com.app.phonemanager") {
let encodedData = try? JSONEncoder().encode(data) let encodedData = try? JSONEncoder().encode(data)
sharedDefaults.set(encodedData, forKey: "widgetSharedData") sharedDefaults.set(encodedData, forKey: "widgetSharedData")
...@@ -91,4 +112,8 @@ struct WidgetData: Codable { ...@@ -91,4 +112,8 @@ struct WidgetData: Codable {
var widget: Int var widget: Int
var battery: Int var battery: Int
var widgetStorage :Int var widgetStorage :Int
var AllSpace: Int
var UseSpace: Int
let batteryState: String
let isCharging: Bool
} }
//
// WidgetBornThenView.swift
// PhoneManager
//
// Created by edy on 2025/5/8.
//
import UIKit
class WidgetBornThenView: UIView ,BatteryStatusDelegate {
var widgetMode = 0 {
didSet{
if widgetMode == 0 {
shapeLayer.strokeColor = UIColor.colorWithHex(hexStr: "#FFFFFF").cgColor
BatteryLayer.strokeColor = UIColor.colorWithHex(hexStr: "#FFFFFF").cgColor
clayer.backgroundColor = UIColor.colorWithHex(hexStr: "#0082FF").cgColor
layer.shadowColor = UIColor.colorWithHex(hexStr: "#0082FF").cgColor
widgetT.textColor = .white
widgetR.textColor = .white
widgetS.textColor = .white
BatteryT.textColor = .white
BatteryR.textColor = .white
BatteryU.textColor = WidgetPublicModel.BatteryState() ? UIColor.white : UIColor(hex: "#cccccc")
BatteryS.textColor = WidgetPublicModel.isLowPowerModeEnabled() ? UIColor.white : UIColor(hex: "#cccccc")
}else if widgetMode == 1 {
shapeLayer.strokeColor = UIColor.colorWithHex(hexStr: "#0082FF").cgColor
BatteryLayer.strokeColor = UIColor.colorWithHex(hexStr: "#0082FF").cgColor
clayer.backgroundColor = UIColor.colorWithHex(hexStr: "#333333").cgColor
layer.shadowColor = UIColor.colorWithHex(hexStr: "#333333").cgColor
widgetT.textColor = .white
widgetR.textColor = .white
widgetS.textColor = UIColor(hex: "#4AE2FF")
BatteryT.textColor = .white
BatteryR.textColor = .white
BatteryU.textColor = WidgetPublicModel.BatteryState() ? UIColor(hex: "#4AE2FF") : UIColor(hex: "#cccccc")
BatteryS.textColor = WidgetPublicModel.isLowPowerModeEnabled() ? UIColor(hex: "#4AE2FF") : UIColor(hex: "#cccccc")
}else{
shapeLayer.strokeColor = UIColor.colorWithHex(hexStr: "#0082FF").cgColor
BatteryLayer.strokeColor = UIColor.colorWithHex(hexStr: "#0082FF").cgColor
layer.shadowColor = UIColor.colorWithHex(hexStr: "#CCE6FF").cgColor
clayer.backgroundColor = UIColor.white.cgColor
widgetT.textColor = .black
widgetR.textColor = .black
widgetS.textColor = UIColor.colorWithHex(hexStr: "#0082FF")
BatteryT.textColor = .black
BatteryR.textColor = .black
BatteryU.textColor = WidgetPublicModel.BatteryState() ? UIColor.colorWithHex(hexStr: "#0082FF") : UIColor(hex: "#cccccc")
BatteryS.textColor = WidgetPublicModel.isLowPowerModeEnabled() ? UIColor(hex: "#666666") : UIColor(hex: "#cccccc")
}
setWidgetInfo()
setBattInfo()
}
}
private func setWidgetInfo() -> Void {
self.layoutIfNeeded()
if widgetMode != 2 {
widgetInfo.image = UIImage(named: "img_storage_widgets")
}else{
widgetInfo.image = UIImage(named: "img_storage_widgets_b")
}
let path = UIBezierPath()
let size:CGSize = widgetInfo.bounds.size
var endangle:CGFloat = 0
let useP:CGFloat = WidgetPublicModel.UseDiskSpace()
endangle = -.pi/2.0 + CGFloat(Double.pi * 2.0 * useP)
path.addArc(withCenter: CGPoint(x: size.width/2.0, y: size.height/2.0),
radius: size.width / 2.0 - 3,
startAngle: -Double.pi/2.0,
endAngle: endangle,
clockwise: true)
shapeLayer.path = path.cgPath
widgetR.text = String(format: "%d%%", Int(round(useP*100)))
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 all = String(format: "%d" ,allInt)
let use = String(format: "%d" ,useInt)
let text = "\(use) of \(all) GB"
widgetS.text = text
}
private func setBattInfo() -> Void {
self.layoutIfNeeded()
if widgetMode != 2 {
BatteryInfo.image = UIImage(named: "img_battery_widgets")
}else{
BatteryInfo.image = UIImage(named: "img_battery_widgets_b")
}
let path1 = UIBezierPath()
let size1:CGSize = BatteryInfo.bounds.size
var endangle1:CGFloat = 0
let end1:CGFloat = CGFloat(WidgetPublicModel.battery() / 100.0)
endangle1 = -Double.pi/2.0 + CGFloat(Double.pi * 2.0 * end1)
path1.addArc(withCenter: CGPoint(x: size1.width/2.0, y: size1.height/2.0),
radius: size1.width / 2.0 - 3,
startAngle: -Double.pi/2.0,
endAngle: endangle1,
clockwise: true)
BatteryLayer.path = path1.cgPath
BatteryR.text = String(format: "%.0f%%", WidgetPublicModel.battery() )
BatteryS.text = "Low Power Mode " + (WidgetPublicModel.isLowPowerModeEnabled() ? "On" : "Off")
BatteryU.text = WidgetPublicModel.BatteryState() ? "Charging now" : "No action"
}
private func setup() -> Void {
widgetInfo.layer.addSublayer(shapeLayer)
BatteryInfo.layer.addSublayer(BatteryLayer)
widgetT.snp.makeConstraints { make in
make.left.equalTo(widgetR.snp.left)
make.bottom.equalTo(widgetR.snp.top).offset(-2)
}
widgetR.snp.makeConstraints { make in
make.left.equalToSuperview().inset(marginLR)
make.bottom.equalTo(self.widgetInfo.snp.centerY).offset(-1)
}
widgetU.snp.makeConstraints { make in
make.left.equalTo(widgetR.snp.left)
make.top.equalTo(widgetR.snp.bottom).offset(2)
}
widgetS.snp.makeConstraints { make in
make.left.equalTo(widgetR.snp.left)
make.top.equalTo(widgetU.snp.bottom).offset(2)
}
BatteryT.snp.makeConstraints { make in
make.left.equalTo(BatteryR.snp.left)
make.bottom.equalTo(BatteryR.snp.top).offset(-2)
}
BatteryR.snp.makeConstraints { make in
make.left.equalToSuperview().inset(marginLR)
make.bottom.equalTo(self.BatteryInfo.snp.centerY).offset(-1)
}
BatteryU.snp.makeConstraints { make in
make.left.equalTo(BatteryR.snp.left)
make.top.equalTo(BatteryR.snp.bottom).offset(2)
}
BatteryS.snp.makeConstraints { make in
make.left.equalTo(BatteryR.snp.left)
make.top.equalTo(BatteryU.snp.bottom).offset(2)
}
widgetInfo.snp.makeConstraints { make in
make.top.equalToSuperview().inset(30)
make.right.equalToSuperview().inset(20)
make.bottom.equalTo(self.snp.centerY).offset(-30)
make.width.equalTo(widgetInfo.snp.height)
}
BatteryInfo.snp.makeConstraints { make in
make.top.equalTo(self.snp.centerY).offset(30)
make.right.equalTo(widgetInfo.snp.right)
make.bottom.equalToSuperview().inset(30)
make.width.equalTo(BatteryInfo.snp.height)
}
self.layoutIfNeeded()
shapeLayer.frame = widgetInfo.bounds
BatteryLayer.frame = BatteryInfo.bounds
}
override init(frame: CGRect) {
super.init(frame: frame)
BatteryMonitorManager.shared.delegate = self
layer.insertSublayer(clayer, at: 0)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setup()
}
func batteryStatusDidUpdate(level: Float, state: UIDevice.BatteryState) {
setBattInfo()
}
private lazy var widgetT: UILabel = {
let l = UILabel()
l.font = UIFont.systemFont(ofSize: 18)
l.text = "Storage"
addSubview(l)
return l
}()
private lazy var widgetR: UILabel = {
let r = UILabel()
r.font = UIFont.boldSystemFont(ofSize: 20)
addSubview(r)
return r
}()
private lazy var widgetU: UILabel = {
let l = UILabel()
l.font = UIFont.boldSystemFont(ofSize: 20)
l.text = "Used"
l.textColor = UIColor(hex: "#cccccc")
addSubview(l)
return l
}()
private lazy var widgetS: UILabel = {
let l = UILabel()
l.font = UIFont.boldSystemFont(ofSize: 18)
addSubview(l)
return l
}()
private lazy var BatteryT: UILabel = {
let l = UILabel()
l.font = UIFont.systemFont(ofSize: 18)
l.text = "Battery"
addSubview(l)
return l
}()
private lazy var BatteryR: UILabel = {
let r = UILabel()
r.font = UIFont.boldSystemFont(ofSize: 20)
addSubview(r)
return r
}()
private lazy var BatteryU: UILabel = {
let l = UILabel()
l.font = UIFont.boldSystemFont(ofSize: 20)
l.text = "No action"
l.textColor = UIColor(hex: "#cccccc")
addSubview(l)
return l
}()
private lazy var BatteryS: UILabel = {
let l = UILabel()
l.font = UIFont.systemFont(ofSize: 18)
l.textColor = UIColor(hex: "#cccccc")
l.text = "Low Power Mode Off"
addSubview(l)
return l
}()
private lazy var clayer: CALayer = {
let l = CALayer()
l.backgroundColor = UIColor.white.cgColor
l.cornerRadius = 20
return l
}()
override func layoutSubviews() {
super.layoutSubviews()
clayer.frame = self.bounds
layer.shadowOffset = CGSize(width: 3, height: 3)
layer.shadowOpacity = 0.7
layer.shadowRadius = 20.0
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
shapeLayer.zPosition = 10
BatteryLayer.zPosition = 10
}
private lazy var widgetInfo: UIImageView = {
let info = UIImageView()
addSubview(info)
info.contentMode = .scaleToFill
return info
}()
private lazy var shapeLayer: CAShapeLayer = {
let sh = CAShapeLayer()
sh.fillColor = UIColor.clear.cgColor
sh.lineWidth = 8
sh.lineCap = .round
return sh
}()
private lazy var BatteryInfo: UIImageView = {
let info = UIImageView()
addSubview(info)
info.contentMode = .scaleToFill
return info
}()
private lazy var BatteryLayer: CAShapeLayer = {
let sh = CAShapeLayer()
sh.fillColor = UIColor.clear.cgColor
sh.lineWidth = 8
sh.lineCap = .round
return sh
}()
}
...@@ -24,13 +24,27 @@ class WidgetTopStackView: UIView { ...@@ -24,13 +24,27 @@ class WidgetTopStackView: UIView {
if type == 0 { if type == 0 {
battryBtn.isSelected = true battryBtn.isSelected = true
storageBtn.isSelected = false storageBtn.isSelected = false
battryBtn.backgroundColor = .white battryBtn.backgroundColor = .white
storageBtn.backgroundColor = .clear storageBtn.backgroundColor = .clear
}else{
bronThem.isSelected = false
bronThem.backgroundColor = .clear
}else if type == 1{
battryBtn.isSelected = false battryBtn.isSelected = false
storageBtn.isSelected = true storageBtn.isSelected = true
battryBtn.backgroundColor = .clear battryBtn.backgroundColor = .clear
storageBtn.backgroundColor = .white storageBtn.backgroundColor = .white
bronThem.isSelected = false
bronThem.backgroundColor = .clear
}else{
battryBtn.isSelected = false
storageBtn.isSelected = false
battryBtn.backgroundColor = .clear
storageBtn.backgroundColor = .clear
bronThem.isSelected = true
bronThem.backgroundColor = .white
} }
} }
} }
...@@ -43,16 +57,37 @@ class WidgetTopStackView: UIView { ...@@ -43,16 +57,37 @@ class WidgetTopStackView: UIView {
} }
private func setUI() -> Void { private func setUI() -> Void {
battryBtn.snp.makeConstraints { make in stack.snp.makeConstraints { make in
make.left.top.bottom.equalToSuperview().inset(4) make.left.top.bottom.right.equalToSuperview().inset(4)
make.right.equalTo(self.snp.centerX)
}
storageBtn.snp.makeConstraints { make in
make.right.top.bottom.equalToSuperview().inset(4)
make.left.equalTo(self.snp.centerX)
} }
stack.addArrangedSubview(battryBtn)
stack.addArrangedSubview(storageBtn)
stack.addArrangedSubview(bronThem)
// battryBtn.snp.makeConstraints { make in
// make.left.top.bottom.equalToSuperview().inset(4)
// make.width.equalTo(self.snp.width).multipliedBy(1/3.0).offset(-8)
// }
// storageBtn.snp.makeConstraints { make in
// make.top.bottom.equalToSuperview().inset(4)
// make.left.equalTo(battryBtn.snp.right)
// make.width.equalTo(battryBtn.snp.width)
// }
// bronThem.snp.makeConstraints { make in
// make.right.top.bottom.equalToSuperview().inset(4)
// make.left.equalTo(storageBtn.snp.right)
// }
} }
private lazy var stack: UIStackView = {
let stack = UIStackView()
stack.spacing = 2
stack.axis = .horizontal
stack.alignment = .fill
stack.distribution = .fillEqually
addSubview(stack)
return stack
}()
private lazy var battryBtn: UIButton = { private lazy var battryBtn: UIButton = {
let b = UIButton(type: .custom) let b = UIButton(type: .custom)
b.tag = 0 b.tag = 0
...@@ -61,7 +96,6 @@ class WidgetTopStackView: UIView { ...@@ -61,7 +96,6 @@ class WidgetTopStackView: UIView {
b.setTitleColor(.colorWithHex(hexStr: "#0082FF"), for: .selected) b.setTitleColor(.colorWithHex(hexStr: "#0082FF"), for: .selected)
b.addTarget(self, action: #selector(widgetTouchs(_:)), for: .touchUpInside) b.addTarget(self, action: #selector(widgetTouchs(_:)), for: .touchUpInside)
b.layer.cornerRadius = 4 b.layer.cornerRadius = 4
addSubview(b)
return b return b
}() }()
...@@ -73,7 +107,17 @@ class WidgetTopStackView: UIView { ...@@ -73,7 +107,17 @@ class WidgetTopStackView: UIView {
b.setTitleColor(.colorWithHex(hexStr: "#0082FF"), for: .selected) b.setTitleColor(.colorWithHex(hexStr: "#0082FF"), for: .selected)
b.addTarget(self, action: #selector(widgetTouchs(_:)), for: .touchUpInside) b.addTarget(self, action: #selector(widgetTouchs(_:)), for: .touchUpInside)
b.layer.cornerRadius = 4 b.layer.cornerRadius = 4
addSubview(b) return b
}()
private lazy var bronThem: UIButton = {
let b = UIButton(type: .custom)
b.tag = 2
b.setTitle("Both", for: .normal)
b.setTitleColor(.colorWithHex(hexStr: "#B3B3B3"), for: .normal)
b.setTitleColor(.colorWithHex(hexStr: "#0082FF"), for: .selected)
b.addTarget(self, action: #selector(widgetTouchs(_:)), for: .touchUpInside)
b.layer.cornerRadius = 4
return b return b
}() }()
......
...@@ -9,21 +9,23 @@ import UIKit ...@@ -9,21 +9,23 @@ import UIKit
class WidgetViewController: BaseViewController { class WidgetViewController: BaseViewController {
enum widgetType { enum widgetType:Int {
case battery case battery = 0
case storage case storage = 1
case bothThem = 2
} }
var widgets:widgetType = .battery { var widgets:widgetType = .battery {
didSet { didSet {
topButs.type = (self.widgets == .battery ? 0 : 1) topButs.type = self.widgets.rawValue
batterySta.widgetType = (self.widgets == .battery ? 0 : 1) batterySta.widgetType = self.widgets.rawValue
} }
} }
var widgetMode = 0 {// 0 1 2 var widgetMode = 0 {// 0 1 2
didSet{ didSet{
batterySta.widgetMode = widgetMode batterySta.widgetMode = widgetMode
born.widgetMode = widgetMode
} }
} }
...@@ -33,11 +35,16 @@ class WidgetViewController: BaseViewController { ...@@ -33,11 +35,16 @@ class WidgetViewController: BaseViewController {
setUI() setUI()
} }
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
widgetMode = 0
}
@objc func setWidgetTouch() -> Void { @objc func setWidgetTouch() -> Void {
let battery = WidgetPublicModel.battery() let battery = WidgetPublicModel.battery()
let storage = WidgetPublicModel.UseDiskSpace() * 100 let storage = WidgetPublicModel.UseDiskSpace() * 100
var widgetIdx = 0 var widgetIdx = 0
widgetIdx = (widgets == .battery ? 0 : 1) * 10 + widgetMode widgetIdx = widgets.rawValue * 10 + widgetMode
widgetAppgourp.share.PushWidgetData(widgetIdx, battery: Int(battery), storage: Int(storage)) widgetAppgourp.share.PushWidgetData(widgetIdx, battery: Int(battery), storage: Int(storage))
PMAlert("Set Widget Successfully") PMAlert("Set Widget Successfully")
} }
...@@ -61,14 +68,19 @@ class WidgetViewController: BaseViewController { ...@@ -61,14 +68,19 @@ class WidgetViewController: BaseViewController {
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
make.top.equalTo(batterySta.snp.bottom).offset(50) make.top.equalTo(batterySta.snp.bottom).offset(50)
} }
born.snp.makeConstraints { make in
make.top.equalTo(batterySta.snp.top)
make.left.right.equalToSuperview().inset(30)
make.height.equalTo(born.snp.width)
}
statesBottom.snp.makeConstraints { make in statesBottom.snp.makeConstraints { make in
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
make.size.equalTo(CGSize(width: 180, height: 40)) make.size.equalTo(CGSize(width: 180, height: 40))
make.top.equalTo(widgetPageCtrol.snp.bottom).offset(50) make.top.equalTo(born.snp.bottom).offset(20)
} }
setWidgetBtn.snp.makeConstraints { make in setWidgetBtn.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(15) make.left.right.equalToSuperview().inset(15)
make.bottom.equalToSuperview().offset(-50) make.bottom.equalToSuperview().offset(-30)
make.height.equalTo(46) make.height.equalTo(46)
} }
} }
...@@ -84,24 +96,37 @@ class WidgetViewController: BaseViewController { ...@@ -84,24 +96,37 @@ class WidgetViewController: BaseViewController {
private lazy var topButs: WidgetTopStackView = { private lazy var topButs: WidgetTopStackView = {
let topbuts = WidgetTopStackView() let topbuts = WidgetTopStackView()
topbuts.type = (self.widgets == .battery ? 0 : 1) topbuts.type = self.widgets.rawValue
topbuts.callback = { [weak self] idx in topbuts.callback = { [weak self] idx in
self?.born.isHidden = true
if idx == 0 { if idx == 0 {
self?.widgets = .battery self?.widgets = .battery
self?.widgetPageCtrol.currentPage = 0 self?.widgetPageCtrol.currentPage = 0
}else{ }else if idx == 1{
self?.widgets = .storage self?.widgets = .storage
self?.widgetPageCtrol.currentPage = 1 self?.widgetPageCtrol.currentPage = 1
}else{
self?.born.isHidden = false
self?.widgets = .bothThem
self?.widgetPageCtrol.currentPage = 2
} }
} }
view.addSubview(topbuts) view.addSubview(topbuts)
return topbuts return topbuts
}() }()
private lazy var born: WidgetBornThenView = {
let born = WidgetBornThenView()
born.layer.cornerRadius = 20
born.isHidden = true
view.addSubview(born)
return born
}()
private lazy var batterySta: WidgetBatteryStView = { private lazy var batterySta: WidgetBatteryStView = {
let stav = WidgetBatteryStView() let stav = WidgetBatteryStView()
stav.layer.cornerRadius = 20 stav.layer.cornerRadius = 20
stav.widgetType = (self.widgets == .battery ? 0 : 1) stav.widgetType = self.widgets.rawValue
stav.widgetMode = widgetMode stav.widgetMode = widgetMode
view.addSubview(stav) view.addSubview(stav)
return stav return stav
...@@ -110,7 +135,7 @@ class WidgetViewController: BaseViewController { ...@@ -110,7 +135,7 @@ class WidgetViewController: BaseViewController {
private lazy var widgetPageCtrol: UIPageControl = { private lazy var widgetPageCtrol: UIPageControl = {
let page = UIPageControl() let page = UIPageControl()
page.currentPage = 0 page.currentPage = 0
page.numberOfPages = 2 page.numberOfPages = 3
page.currentPageIndicatorTintColor = .colorWithHex(hexStr: "#0082FF") page.currentPageIndicatorTintColor = .colorWithHex(hexStr: "#0082FF")
page.pageIndicatorTintColor = .colorWithHex(hexStr: "#C6CEE0") page.pageIndicatorTintColor = .colorWithHex(hexStr: "#C6CEE0")
view.addSubview(page) view.addSubview(page)
......
//
// PMScaleImageView.swift
// PhoneManager
//
// Created by edy on 2025/5/7.
//
import UIKit
class PMScaleImageView: UIView , UIScrollViewDelegate {
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setup()
}
var icon:UIImage? {
didSet {
showImg.image = icon
DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: {
let size = self.icon?.size ?? CGSize()
// self.showImg.snp.remakeConstraints({ make in
// make.size.equalTo(size)
// })
// self.layoutIfNeeded()
// self.showImg.center = CGPoint(x: self.scroll.width/2.0, y: self.scroll.height/2.0)
})
}
}
private func setup() -> Void {
scroll.snp.makeConstraints { make in
make.left.right.bottom.top.equalToSuperview()
}
showImg.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.width.height.equalToSuperview()
}
}
private lazy var showImg: UIImageView = {
let iv = UIImageView()
iv.contentMode = .center
scroll.addSubview(iv)
return iv
}()
private lazy var scroll: UIScrollView = {
let scroll = UIScrollView()
scroll.delegate = self
scroll.showsVerticalScrollIndicator = false
scroll.showsHorizontalScrollIndicator = false
scroll.minimumZoomScale = 1.0
scroll.maximumZoomScale = 3.0
addSubview(scroll)
return scroll
}()
func scrollViewDidZoom(_ scrollView: UIScrollView) {
Print(scrollView.zoomScale)
if scrollView.zoomScale > 1.5 {
self.Radius = 16
}else{
self.Radius = 0
}
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return showImg
}
}
...@@ -30,7 +30,6 @@ extension UIView { ...@@ -30,7 +30,6 @@ extension UIView {
} }
func cornerCut(radius:CGFloat,corner:UIRectCorner){ func cornerCut(radius:CGFloat,corner:UIRectCorner){
let maskPath = UIBezierPath.init(roundedRect: bounds, byRoundingCorners: corner, cornerRadii: CGSize.init(width: radius, height: radius)) let maskPath = UIBezierPath.init(roundedRect: bounds, byRoundingCorners: corner, cornerRadii: CGSize.init(width: radius, height: radius))
let maskLayer = CAShapeLayer() let maskLayer = CAShapeLayer()
maskLayer.frame = bounds maskLayer.frame = bounds
......
...@@ -2,10 +2,8 @@ ...@@ -2,10 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>NSContactsUsageDescription</key> <key>GADApplicationIdentifier</key>
<string>Phone Manager needs access to your contacts to find and merge duplicate contacts</string> <string>ca-app-pub-3940256099942544~1458002511</string>
<key>NSUserTrackingUsageDescription</key>
<string>We need your permission to track your usage habits in order to provide a more personalized advertising experience</string>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsArbitraryLoads</key> <key>NSAllowsArbitraryLoads</key>
...@@ -18,15 +16,10 @@ ...@@ -18,15 +16,10 @@
<string>ChargeShowIntent</string> <string>ChargeShowIntent</string>
<string>LaunchAppIntent</string> <string>LaunchAppIntent</string>
</array> </array>
<key>NSWidgetUsageDescription</key>
<string>Need to access device data to provide real-time information</string>
<key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key> <key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key>
<true/> <true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
</dict>
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
<key>SKAdNetworkItems</key> <key>SKAdNetworkItems</key>
<array> <array>
<dict> <dict>
...@@ -226,6 +219,11 @@ ...@@ -226,6 +219,11 @@
<string>3qcr597p9d.skadnetwork</string> <string>3qcr597p9d.skadnetwork</string>
</dict> </dict>
</array> </array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
</dict>
<key>UIBackgroundModes</key> <key>UIBackgroundModes</key>
<array> <array>
<string>processing</string> <string>processing</string>
......
# Uncomment the next line to define a global platform for your project # 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 target 'PhoneManager' do
# Comment the next line if you don't want to use dynamic frameworks # Comment the next line if you don't want to use dynamic frameworks
......
...@@ -12,7 +12,7 @@ import SwiftUI ...@@ -12,7 +12,7 @@ import SwiftUI
struct Provider: TimelineProvider { struct Provider: TimelineProvider {
func placeholder(in context: Context) -> SimpleEntry { func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), widgets: 0, widgetBattery: 0, widgetStorage: 0) SimpleEntry(date: Date() , widgets: 0, widgetBattery: 0, widgetStorage: 0, widgetAllSpace: 0 ,widgetUseSpace: 0 ,batteryState: "Off" , isCharging: false)
} }
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) { func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) {
...@@ -22,7 +22,7 @@ struct Provider: TimelineProvider { ...@@ -22,7 +22,7 @@ struct Provider: TimelineProvider {
func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) { func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) {
let entry = loadSharedData() let entry = loadSharedData()
let timeline = Timeline(entries: [entry], policy: .after(Date().addingTimeInterval(120))) let timeline = Timeline(entries: [entry], policy: .after(Date().addingTimeInterval(60)))
completion(timeline) completion(timeline)
} }
...@@ -31,9 +31,9 @@ struct Provider: TimelineProvider { ...@@ -31,9 +31,9 @@ struct Provider: TimelineProvider {
let data:Data = sharedDefaults.object(forKey: "widgetSharedData") as? Data, let data:Data = sharedDefaults.object(forKey: "widgetSharedData") as? Data,
let decodedData = try? JSONDecoder().decode(WidgetData.self, from: data) let decodedData = try? JSONDecoder().decode(WidgetData.self, from: data)
else { else {
return SimpleEntry(date: Date(), widgets: 0, widgetBattery: 0, widgetStorage: 0) return SimpleEntry(date: Date(), widgets: 0, widgetBattery: 0, widgetStorage: 0 ,widgetAllSpace: 0 ,widgetUseSpace: 0 ,batteryState: "Off" , isCharging: false)
} }
return SimpleEntry(date: Date(), widgets: decodedData.widget, widgetBattery: decodedData.battery, widgetStorage: decodedData.widgetStorage) return SimpleEntry(date: Date(), widgets: decodedData.widget, widgetBattery: decodedData.battery, widgetStorage: decodedData.widgetStorage,widgetAllSpace: decodedData.AllSpace,widgetUseSpace: decodedData.UseSpace ,batteryState: decodedData.batteryState ,isCharging: decodedData.isCharging)
} }
} }
...@@ -42,6 +42,10 @@ struct WidgetData: Codable { ...@@ -42,6 +42,10 @@ struct WidgetData: Codable {
var widget: Int var widget: Int
var battery: Int var battery: Int
var widgetStorage: Int var widgetStorage: Int
var AllSpace: Int
var UseSpace: Int
let batteryState: String
let isCharging: Bool
} }
...@@ -56,99 +60,311 @@ struct WidgetStyle : Codable { ...@@ -56,99 +60,311 @@ struct WidgetStyle : Codable {
struct SimpleEntry: TimelineEntry { struct SimpleEntry: TimelineEntry {
let date: Date let date: Date
let widgets:Int var widgets:Int
let widgetBattery:Int let widgetBattery:Int
let widgetStorage:Int let widgetStorage:Int
let widgetAllSpace:Int
let widgetUseSpace:Int
let batteryState: String // 是否低电量模式
let isCharging: Bool // 是否在充电
} }
struct BatteryWidgetEntryView : View { func getShowImage(_ entry:SimpleEntry ,_ type:Int) -> String {
var img = ""
if type == 0 {
if (entry.widgets % 10) != 2 {
img = "img_storage_widgets"
}else{
img = "img_storage_widgets_b"
}
}else{
if (entry.widgets % 10) != 2 {
img = "img_battery_widgets"
}else{
img = "img_battery_widgets_b"
}
}
return img
}
func getwidgetStyle(_ entry: SimpleEntry , _ isBattery:Bool = false) -> WidgetStyle {
var icon = ""
var lt = "Battery"
var anag = 0
if isBattery {
if (entry.widgets % 10) != 2 {
icon = "img_battery_widgets"
}else{
icon = "img_battery_widgets_b"
}
anag = entry.widgetBattery
}else{
lt = "Storage"
if (entry.widgets % 10) != 2 {
icon = "img_storage_widgets"
}else{
icon = "img_storage_widgets_b"
}
anag = entry.widgetStorage
}
var tcolor = "FFFFFF"
var bg = "0082FF"
var line = "FFFFFF"
if entry.widgets % 10 == 0 {
} else if entry.widgets % 10 == 1 {
bg = "333333"
line = "0082FF"
}else{
line = "0082FF"
bg = "FFFFFF"
tcolor = "0082FF"
}
return WidgetStyle(textColor: tcolor, lText: lt, backgound: bg, LineColor: line ,icon:icon ,Angle: Double(anag))
}
func battteryColor(entry:SimpleEntry) -> Color {
if entry.widgets % 10 == 0 {
return .white
}else if entry.widgets % 10 == 1 {
return .white
}else{
return .black
}
}
fileprivate func useSpaceColor(entry:SimpleEntry) -> Color {
if entry.widgets % 10 == 0 {
return .white
}else if entry.widgets % 10 == 1 {
return Color("4AE2FF")
}else{
return Color("0082FF")
}
}
func ActionColor(entry:SimpleEntry) -> Color {
if entry.isCharging {
if entry.widgets % 10 == 0 {
return .white
}else if entry.widgets % 10 == 1 {
return Color("4AE2FF")
}else{
return Color("0082FF")
}
}else{
return Color("cccccc")
}
}
fileprivate func PowerColor(entry:SimpleEntry) -> Color {
if entry.batteryState == "On" {
if entry.widgets % 10 == 0 {
return .white
}else if entry.widgets % 10 == 1 {
return Color("4AE2FF")
}else{
return Color("666666")
}
}else{
return Color("cccccc")
}
}
fileprivate func contentStack(_ entry:SimpleEntry) -> some View {
return ZStack {
Color(getwidgetStyle(entry).backgound).ignoresSafeArea()
VStack(spacing: 50 , content: {
HStack(alignment: .center, content: {
VStack(spacing: 5, content: {
Text("Storage").frame(maxWidth: .infinity ,alignment: .topLeading).font(.system(size: 18,weight: .medium)).foregroundColor(battteryColor(entry: entry))
Text(String(entry.widgetStorage) + "%").frame(maxWidth: .infinity ,alignment: .topLeading).foregroundColor(battteryColor(entry: entry)).font(.system(size: 24,weight: .bold))
Text("Used").frame(maxWidth: .infinity ,alignment: .topLeading).foregroundColor(Color("CCCCCC")).font(.system(size: 20,weight: .bold))
Text(String(entry.widgetUseSpace) + " of " + String(entry.widgetAllSpace) + "GB").frame(maxWidth: .infinity ,alignment: .topLeading).foregroundColor(useSpaceColor(entry: entry)).font(.system(size: 18, weight: .bold))
})
ZStack {
Image(getShowImage(entry, 0))
ArcShape(startAngle: .degrees(-90), endAngle: .degrees( Double(entry.widgetStorage)/100.0 * 360.0 - 90.0), clockwise: false).stroke(Color(getwidgetStyle(entry).LineColor), style: StrokeStyle(lineWidth: 5, lineCap: .round) )
}.frame(width: 68, height: 68, alignment: .center)
})
HStack(alignment: .center, content: {
VStack(spacing: 15, content: {
VStack(spacing: 1) {
Text("Battery").frame(maxWidth: .infinity ,alignment: .topLeading).font(.system(size: 18,weight: .medium)).foregroundColor(battteryColor(entry: entry))
Text(String(entry.widgetBattery) + "%").frame(maxWidth: .infinity ,alignment: .topLeading).foregroundColor(battteryColor(entry: entry)).font(.system(size: 24,weight: .bold))
}
VStack(spacing: 1) {
Text(entry.isCharging ? "Charging now" : "No action").frame(maxWidth: .infinity ,alignment: .topLeading).foregroundColor(ActionColor(entry: entry)).font(.system(size: 20,weight: .medium))
Text("Low Power Mode \(entry.batteryState)").frame(maxWidth: .infinity ,alignment: .topLeading).foregroundColor(PowerColor(entry: entry)).font(.system(size: 16, weight: .medium))
}
})
ZStack {
Image(getShowImage(entry, 1))
ArcShape(startAngle: .degrees(-90), endAngle: .degrees(Double(entry.widgetBattery)/100.0 * 360.0 - 90.0), clockwise: false).stroke(Color(getwidgetStyle(entry).LineColor), style: StrokeStyle(lineWidth: 5, lineCap: .round))
}.frame(width: 68, height: 68, alignment: .center)
})
}).padding(EdgeInsets(top: 10, leading: 20, bottom: 10, trailing: 30))
}
}
struct BatteryWidgetBothView : View {
var entry: Provider.Entry
var body: some View {
if #available(iOSApplicationExtension 17.0, *) {
contentStack(entry).containerBackground(for: .widget) {
Color(getwidgetStyle(entry).backgound)
}
} else {
contentStack(entry)
}
}
}
struct BatteryWidgetView : View {
var entry: Provider.Entry var entry: Provider.Entry
var body: some View { var body: some View {
if #available(iOSApplicationExtension 17.0, *) { if #available(iOSApplicationExtension 17.0, *) {
ZStack { ZStack {
Color(getwidgetStyle().backgound).ignoresSafeArea() Color(getwidgetStyle(entry).backgound).ignoresSafeArea()
VStack { VStack {
HStack(alignment: .center) { HStack(alignment: .center) {
Text(getwidgetStyle().lText).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topLeading).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle().textColor)) Text(getwidgetStyle(entry).lText).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topLeading).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle(entry).textColor))
VStack(alignment: .center, spacing: 2) { VStack(alignment: .center, spacing: 2) {
Text(String(getwidgetStyle().Angle) + "%" ).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topTrailing).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle().textColor)) Text(String(getwidgetStyle(entry).Angle) + "%" ).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topTrailing).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle(entry).textColor))
if entry.widgets / 10 == 1 { if entry.widgets / 10 == 1 {
Text("Used").frame(maxWidth: .infinity,alignment: .topTrailing).font(.system(size: 10)).foregroundColor(Color(getwidgetStyle().textColor)).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 5)) Text("Used").frame(maxWidth: .infinity,alignment: .topTrailing).font(.system(size: 10)).foregroundColor(Color(getwidgetStyle(entry).textColor)).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 5))
} }
} }
} }
ZStack { ZStack {
Image(getwidgetStyle().icon) Image(getwidgetStyle(entry).icon)
ArcShape(startAngle: .degrees(-90), endAngle: .degrees(getwidgetStyle().Angle/100.0 * 360.0 - 90.0), clockwise: false) ArcShape(startAngle: .degrees(-90), endAngle: .degrees(getwidgetStyle(entry).Angle/100.0 * 360.0 - 90.0), clockwise: false)
.stroke(Color(getwidgetStyle().LineColor), style: StrokeStyle(lineWidth: 5, lineCap: .round) ) .stroke(Color(getwidgetStyle(entry).LineColor), style: StrokeStyle(lineWidth: 5, lineCap: .round) )
} }
}.padding(EdgeInsets(top: 16, leading: 10, bottom: 30, trailing: 10)) }.padding(EdgeInsets(top: 16, leading: 0, bottom: 30, trailing: 0))
} }
.containerBackground(for: .widget) { .containerBackground(for: .widget) {
Color(getwidgetStyle().backgound) Color(getwidgetStyle(entry).backgound)
} }
} else { } else {
ZStack { ZStack {
Color(getwidgetStyle().backgound).ignoresSafeArea() Color(getwidgetStyle(entry).backgound).ignoresSafeArea()
VStack { VStack {
HStack(alignment: .center) { HStack(alignment: .center) {
Text(getwidgetStyle().lText).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topLeading).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle().textColor)) Text(getwidgetStyle(entry).lText).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topLeading).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle(entry).textColor))
VStack(alignment: .center, spacing: 2) { VStack(alignment: .center, spacing: 2) {
Text(String(getwidgetStyle().Angle) + "%" ).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topTrailing).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle().textColor)) Text(String(getwidgetStyle(entry).Angle) + "%" ).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topTrailing).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle(entry).textColor))
if entry.widgets / 10 == 1 { if entry.widgets / 10 == 1 {
Text("Used").frame(maxWidth: .infinity,alignment: .topTrailing).font(.system(size: 10)).foregroundColor(Color(getwidgetStyle().textColor)).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 5)) Text("Used").frame(maxWidth: .infinity,alignment: .topTrailing).font(.system(size: 10)).foregroundColor(Color(getwidgetStyle(entry).textColor)).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 5))
} }
} }
} }
ZStack { ZStack {
Image(getwidgetStyle().icon) Image(getwidgetStyle(entry).icon)
ArcShape(startAngle: .degrees(-90), endAngle: .degrees(getwidgetStyle().Angle/100.0 * 360.0 - 90.0), clockwise: false) ArcShape(startAngle: .degrees(-90), endAngle: .degrees(getwidgetStyle(entry).Angle/100.0 * 360.0 - 90.0), clockwise: false)
.stroke(Color(getwidgetStyle().LineColor), style: StrokeStyle(lineWidth: 5, lineCap: .round) ) .stroke(Color(getwidgetStyle(entry).LineColor), style: StrokeStyle(lineWidth: 5, lineCap: .round) )
} }
}.padding(EdgeInsets(top: 16, leading: 10, bottom: 30, trailing: 10)) }.padding(EdgeInsets(top: 16, leading: 10, bottom: 30, trailing: 10))
} }
} }
} }
}
func getwidgetStyle() -> WidgetStyle {
var icon = "" struct BatteryWidgetStorageView : View {
var lt = "Battery" var entry: Provider.Entry
var anag = 0 var body: some View {
if entry.widgets / 10 == 0 { if #available(iOSApplicationExtension 17.0, *) {
if (entry.widgets % 10) != 2 { ZStack {
icon = "img_battery_widgets" Color(getwidgetStyle(entry,true).backgound).ignoresSafeArea()
}else{ VStack {
icon = "img_battery_widgets_b" HStack(alignment: .center) {
Text(getwidgetStyle(entry,true).lText).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topLeading).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle(entry,true).textColor))
VStack(alignment: .center, spacing: 2) {
Text(String(getwidgetStyle(entry,true).Angle) + "%" ).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topTrailing).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle(entry,true).textColor))
if entry.widgets / 10 == 1 {
Text("Used").frame(maxWidth: .infinity,alignment: .topTrailing).font(.system(size: 10)).foregroundColor(Color(getwidgetStyle(entry,true).textColor)).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 5))
}
}
}
ZStack {
Image(getwidgetStyle(entry,true).icon)
ArcShape(startAngle: .degrees(-90), endAngle: .degrees(getwidgetStyle(entry,true).Angle/100.0 * 360.0 - 90.0), clockwise: false)
.stroke(Color(getwidgetStyle(entry,true).LineColor), style: StrokeStyle(lineWidth: 5, lineCap: .round) )
}
}.padding(EdgeInsets(top: 16, leading: 0, bottom: 30, trailing: 0))
} }
anag = entry.widgetBattery .containerBackground(for: .widget) {
}else{ Color(getwidgetStyle(entry,true).backgound)
lt = "Storage" }
if (entry.widgets % 10) != 2 { } else {
icon = "img_storage_widgets" ZStack {
}else{ Color(getwidgetStyle(entry,true).backgound).ignoresSafeArea()
icon = "img_storage_widgets_b" VStack {
HStack(alignment: .center) {
Text(getwidgetStyle(entry,true).lText).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topLeading).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle(entry,true).textColor))
VStack(alignment: .center, spacing: 2) {
Text(String(getwidgetStyle(entry,true).Angle) + "%" ).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topTrailing).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle(entry,true).textColor))
if entry.widgets / 10 == 1 {
Text("Used").frame(maxWidth: .infinity,alignment: .topTrailing).font(.system(size: 10)).foregroundColor(Color(getwidgetStyle(entry,true).textColor)).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 5))
}
}
}
ZStack {
Image(getwidgetStyle(entry,true).icon)
ArcShape(startAngle: .degrees(-90), endAngle: .degrees(getwidgetStyle(entry,true).Angle/100.0 * 360.0 - 90.0), clockwise: false)
.stroke(Color(getwidgetStyle(entry,true).LineColor), style: StrokeStyle(lineWidth: 5, lineCap: .round) )
}
}.padding(EdgeInsets(top: 16, leading: 10, bottom: 30, trailing: 10))
} }
anag = entry.widgetStorage
}
var tcolor = "FFFFFF"
var bg = "0082FF"
var line = "FFFFFF"
if entry.widgets % 10 == 0 {
} else if entry.widgets % 10 == 1 {
bg = "333333"
line = "0082FF"
}else{
line = "0082FF"
bg = "FFFFFF"
tcolor = "0082FF"
} }
return WidgetStyle(textColor: tcolor, lText: lt, backgound: bg, LineColor: line ,icon:icon ,Angle: Double(anag))
} }
} }
struct EmptyView : View {
var body: some View {
ZStack {
Color.clear.ignoresSafeArea()
Text("").foregroundColor(.clear)
}
}
}
struct BatteryWidgetEntryView : View {
var entry: Provider.Entry
@Environment(\.widgetFamily) var family
var body: some View {
switch family {
case .systemSmall:
BatteryWidgetView(entry: entry)
case .systemMedium:
BatteryWidgetView(entry: entry)
case .systemLarge:
BatteryWidgetBothView(entry: entry)
default:
EmptyView()
}
}
}
struct BatteryStorageEntryView : View {
var entry: Provider.Entry
@Environment(\.widgetFamily) var family
var body: some View {
switch family {
case .systemSmall:
BatteryWidgetStorageView(entry: entry)
case .systemMedium:
BatteryWidgetStorageView(entry: entry)
case .systemLarge:
BatteryWidgetBothView(entry: entry)
default:
EmptyView()
}
}
}
struct ArcShape: Shape { struct ArcShape: Shape {
var startAngle: Angle var startAngle: Angle
var endAngle: Angle var endAngle: Angle
...@@ -173,8 +389,88 @@ struct BatteryWidget: Widget { ...@@ -173,8 +389,88 @@ struct BatteryWidget: Widget {
var body: some WidgetConfiguration { var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in StaticConfiguration(kind: kind, provider: Provider()) { entry in
BatteryWidgetEntryView(entry: entry) BatteryWidgetEntryView(entry: entry)
}.configurationDisplayName("").description("") }.configurationDisplayName("Storage").description("Monitor your storage space")
.supportedFamilies([.systemSmall , .systemMedium]) .supportedFamilies([.systemSmall ,.systemMedium])
}
}
struct BatteryWidget1: Widget {
let kind: String = "BatteryWidget1"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
BatteryStorageEntryView(entry: entry)
}.configurationDisplayName("Battery").description("Monitor your battery")
.supportedFamilies([.systemSmall ,.systemMedium])
}
}
struct BatteryWidget2: Widget {
let kind: String = "BatteryWidget2"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
BatteryStorageEntryView(entry: entry)
}.configurationDisplayName("Both").description("Monitor your battery and storage space")
.supportedFamilies([.systemLarge])
}
}
struct AWidgetStorageView : View {
var entry: Provider.Entry
var body: some View {
if #available(iOSApplicationExtension 17.0, *) {
ZStack {
Text("\(entry.widgetBattery)")
}.foregroundColor(Color("333333"))
.containerBackground(for: .widget) {
AccessoryWidgetBackground()
}
} else {
ZStack {
Text("Hello")
}
}
}
}
struct LockScreenWidgetView :View {
var entry: Provider.Entry
@Environment(\.widgetFamily) var family
var body: some View {
switch family {
case .accessoryCircular:
AWidgetStorageView(entry: entry)
default:
EmptyView()
}
}
}
struct widgetLockSreenView: Widget {
let kind = "com.app.lockscreen.widget"
var body: some WidgetConfiguration {
if #available(iOSApplicationExtension 16.0, *) {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
LockScreenWidgetView(entry: entry)
}
.configurationDisplayName("Storage")
.description("Monitor your storage space")
.supportedFamilies([
.accessoryCircular,
])
} else {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
LockScreenWidgetView(entry: entry)
}
.configurationDisplayName("")
.description("")
.supportedFamilies([])
}
} }
} }
...@@ -11,12 +11,14 @@ import SwiftUI ...@@ -11,12 +11,14 @@ import SwiftUI
@main @main
struct widgetBundle: WidgetBundle { struct widgetBundle: WidgetBundle {
var body: some Widget { var body: some Widget {
BatteryWidget() widgetLockSreenView()
// BatteryWidget()
// BatteryWidget1()
// BatteryWidget2()
} }
} }
extension Color { extension Color {
init(_ hex:String = "FFFFFF") { init(_ hex:String = "FFFFFF") {
let scanner = Scanner(string: hex) let scanner = Scanner(string: hex)
scanner.currentIndex = hex.startIndex 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