Commit 7f7333dc authored by yqz's avatar yqz

widget 1001

parent aa7e9222
......@@ -7,9 +7,22 @@
objects = {
/* Begin PBXBuildFile section */
0496DEF32D9E3F58005B2834 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04BD915D2D9D68AD00055CEB /* WidgetKit.framework */; };
0496DEF42D9E3F58005B2834 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04BD915F2D9D68AD00055CEB /* SwiftUI.framework */; };
0496DEFF2D9E3F59005B2834 /* widgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 0496DEF22D9E3F57005B2834 /* widgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
3A00E856852A8783E544CD7D /* Pods_PhoneManager.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6028F60B696E2F97EAA2325C /* Pods_PhoneManager.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
0496DEFD2D9E3F59005B2834 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = EB388E532D8A61A800629B0D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 0496DEF12D9E3F57005B2834;
remoteInfo = widgetExtension;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
04BD916E2D9D68AF00055CEB /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
......@@ -17,6 +30,7 @@
dstPath = "";
dstSubfolderSpec = 13;
files = (
0496DEFF2D9E3F59005B2834 /* widgetExtension.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
......@@ -24,6 +38,8 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0496DEF22D9E3F57005B2834 /* widgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = widgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
0496DF042D9E3FA7005B2834 /* widgetExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = widgetExtension.entitlements; sourceTree = "<group>"; };
04BD915D2D9D68AD00055CEB /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
04BD915F2D9D68AD00055CEB /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
295785B9009F20AC4C1C36C4 /* Pods-PhoneManager.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PhoneManager.debug.xcconfig"; path = "Target Support Files/Pods-PhoneManager/Pods-PhoneManager.debug.xcconfig"; sourceTree = "<group>"; };
......@@ -33,6 +49,13 @@
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
0496DF032D9E3F59005B2834 /* Exceptions for "widget" folder in "widgetExtension" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Info.plist,
);
target = 0496DEF12D9E3F57005B2834 /* widgetExtension */;
};
EB388E6D2D8A61AA00629B0D /* Exceptions for "PhoneManager" folder in "PhoneManager" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
......@@ -43,6 +66,14 @@
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
0496DEF52D9E3F58005B2834 /* widget */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
0496DF032D9E3F59005B2834 /* Exceptions for "widget" folder in "widgetExtension" target */,
);
path = widget;
sourceTree = "<group>";
};
EB388E5D2D8A61A800629B0D /* PhoneManager */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
......@@ -54,6 +85,15 @@
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
0496DEEF2D9E3F57005B2834 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0496DEF42D9E3F58005B2834 /* SwiftUI.framework in Frameworks */,
0496DEF32D9E3F58005B2834 /* WidgetKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
EB388E582D8A61A800629B0D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
......@@ -87,7 +127,9 @@
EB388E522D8A61A800629B0D = {
isa = PBXGroup;
children = (
0496DF042D9E3FA7005B2834 /* widgetExtension.entitlements */,
EB388E5D2D8A61A800629B0D /* PhoneManager */,
0496DEF52D9E3F58005B2834 /* widget */,
EB388E5C2D8A61A800629B0D /* Products */,
CB2ACD1E9442B4500087E831 /* Pods */,
27ECDADD9059AB5043B8E1E9 /* Frameworks */,
......@@ -98,6 +140,7 @@
isa = PBXGroup;
children = (
EB388E5B2D8A61A800629B0D /* PhoneManager.app */,
0496DEF22D9E3F57005B2834 /* widgetExtension.appex */,
);
name = Products;
sourceTree = "<group>";
......@@ -105,6 +148,28 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
0496DEF12D9E3F57005B2834 /* widgetExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 0496DF022D9E3F59005B2834 /* Build configuration list for PBXNativeTarget "widgetExtension" */;
buildPhases = (
0496DEEE2D9E3F57005B2834 /* Sources */,
0496DEEF2D9E3F57005B2834 /* Frameworks */,
0496DEF02D9E3F57005B2834 /* Resources */,
);
buildRules = (
);
dependencies = (
);
fileSystemSynchronizedGroups = (
0496DEF52D9E3F58005B2834 /* widget */,
);
name = widgetExtension;
packageProductDependencies = (
);
productName = widgetExtension;
productReference = 0496DEF22D9E3F57005B2834 /* widgetExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
EB388E5A2D8A61A800629B0D /* PhoneManager */ = {
isa = PBXNativeTarget;
buildConfigurationList = EB388E6E2D8A61AA00629B0D /* Build configuration list for PBXNativeTarget "PhoneManager" */;
......@@ -119,6 +184,7 @@
buildRules = (
);
dependencies = (
0496DEFE2D9E3F59005B2834 /* PBXTargetDependency */,
);
fileSystemSynchronizedGroups = (
EB388E5D2D8A61A800629B0D /* PhoneManager */,
......@@ -138,6 +204,9 @@
LastSwiftUpdateCheck = 1620;
LastUpgradeCheck = 1620;
TargetAttributes = {
0496DEF12D9E3F57005B2834 = {
CreatedOnToolsVersion = 16.2;
};
EB388E5A2D8A61A800629B0D = {
CreatedOnToolsVersion = 16.2;
LastSwiftMigration = 1620;
......@@ -159,11 +228,19 @@
projectRoot = "";
targets = (
EB388E5A2D8A61A800629B0D /* PhoneManager */,
0496DEF12D9E3F57005B2834 /* widgetExtension */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
0496DEF02D9E3F57005B2834 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
EB388E592D8A61A800629B0D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
......@@ -216,6 +293,13 @@
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
0496DEEE2D9E3F57005B2834 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
EB388E572D8A61A800629B0D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
......@@ -225,7 +309,89 @@
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
0496DEFE2D9E3F59005B2834 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 0496DEF12D9E3F57005B2834 /* widgetExtension */;
targetProxy = 0496DEFD2D9E3F59005B2834 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
0496DF002D9E3F59005B2834 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = widgetExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 6K23946NQ5;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = widget/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = widget;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.app.phonemanager.bswidget;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = phonemanager_widget_dev;
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
0496DF012D9E3F59005B2834 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = widgetExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 6K23946NQ5;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = widget/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = widget;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.app.phonemanager.bswidget;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = phonemanager_widget_dev;
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
EB388E6F2D8A61AA00629B0D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 295785B9009F20AC4C1C36C4 /* Pods-PhoneManager.debug.xcconfig */;
......@@ -435,6 +601,15 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
0496DF022D9E3F59005B2834 /* Build configuration list for PBXNativeTarget "widgetExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
0496DF002D9E3F59005B2834 /* Debug */,
0496DF012D9E3F59005B2834 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
EB388E562D8A61A800629B0D /* Build configuration list for PBXProject "PhoneManager" */ = {
isa = XCConfigurationList;
buildConfigurations = (
......
......@@ -28,6 +28,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
window?.makeKeyAndVisible()
}
let battery = WidgetPublicModel.battery()
let storage = WidgetPublicModel.UseDiskSpace() * 100
widgetAppgourp.share.PushWidgetData(battery: Int(battery), storage: Int(storage))
return true
}
......@@ -69,7 +72,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
safeHeight = UIApplication.shared.delegate?.window??.safeAreaInsets.bottom ?? 0
}else {
safeHeight = 0
}
}
......
......@@ -39,10 +39,8 @@ class ChargeViewController:BaseViewController {
if let cModel = model as? ChargeViewCollectionModel {
let vc:ChargeInfoViewController = ChargeInfoViewController(model: cModel, type: ChargeInfoViewController.ChargeInfoType.setting)
self.navigationController?.pushViewController(vc, animated: true)
}
}
}
......
......@@ -21,7 +21,7 @@ class SecretSetViewController: BaseViewController, UITextFieldDelegate {
if secretType == .create {
setTitle.text = "Create New PlN"
}else{
setTitle.text = "Please Enter PlN"
}
}
......@@ -41,7 +41,16 @@ class SecretSetViewController: BaseViewController, UITextFieldDelegate {
didSet {
collect.reloadData()
if Secret.count == 4 {
if secretType == .verify {
let Ps:String = UserDefaults.standard.object(forKey: SecretViewController.psKey) as? String ?? ""
if Ps != Secret {
alert("Pin Verification Failed")
Secret = ""
return
}
}else{
UserDefaults.standard.set(Secret, forKey: SecretViewController.psKey)
}
guard Callback != nil else {
return
}
......@@ -57,7 +66,7 @@ class SecretSetViewController: BaseViewController, UITextFieldDelegate {
view.addSubview(collect)
setInfo.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalToSuperview().offset(62)
make.top.equalTo(titleView.snp.bottom).offset(62)
}
setTitle.snp.makeConstraints { make in
make.centerX.equalToSuperview()
......
//
// SecretShowImgVideoController.swift
// PhoneManager
//
// Created by edy on 2025/4/3.
//
import UIKit
class SecretShowImgVideoController: BaseViewController {
var imageVideoPath:String = ""
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
showPlay()
}
private func setUI( _ icon:UIImage) -> Void {
showImage.snp.remakeConstraints { make in
make.left.right.equalToSuperview().inset(24)
make.top.equalTo(self.titleView.snp.bottom).offset(20)
make.height.equalTo(self.showImage.snp.width).multipliedBy(icon.size.height/icon.size.width)
}
}
private func showPlay() -> Void {
if imageVideoPath.hasSuffix(".png") {
self.showImage.isHidden = false
imageVideoPath.loadPhotoOrVideo({[weak self] dur, icon in
self?.showImage.image = icon
self?.setUI(icon)
})
}else{
player.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(20)
make.top.equalTo(self.titleView.snp.bottom).offset(20)
make.bottom.equalToSuperview().offset(-40)
}
player.isHidden = false
let url = "SecretIm".document().appendingPathComponent(imageVideoPath)
player.playVideo(from: url)
}
}
private lazy var showImage: UIImageView = {
let img = UIImageView()
img.contentMode = .scaleAspectFill
img.isHidden = true
view.addSubview(img)
return img
}()
private lazy var player: SecretVideoPlayer = {
let p = SecretVideoPlayer()
view.addSubview(p)
p.layer.cornerRadius = 8
p.clipsToBounds = true
p.isHidden = true
return p
}()
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
player.pause()
}
}
......@@ -106,6 +106,7 @@ class SecretViewController: BaseViewController {
let set = SecretSetViewController()
set.Callback = { suc in
self?.isVerify = suc
sender.isSelected = suc
}
self?.navigationController?.pushViewController(set, animated: true)
}
......@@ -114,6 +115,16 @@ class SecretViewController: BaseViewController {
}
alert.show()
}else{
if isVerify == false {
let set = SecretSetViewController()
set.secretType = .verify
set.Callback = {[weak self] suc in
self?.isVerify = suc
sender.isSelected = suc
}
self.navigationController?.pushViewController(set, animated: true)
return
}
sender.isSelected = !sender.isSelected
isVerify = sender.isSelected;
}
......@@ -250,17 +261,16 @@ extension SecretViewController : UICollectionViewDelegate,UICollectionViewDataSo
cell.clipsToBounds = true
cell.isSelect = selectArray.contains((indexPath.row))
cell.imageText = data[indexPath.row]
cell.callback = { [weak self] in
self?.selectImgVideo(indexPath.row)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if selectArray.contains((indexPath.row)) {
selectArray.remove((indexPath.row))
}else{
selectArray.add((indexPath.row))
}
seletedAllBtn.isSelected = selectArray.count == data.count
collectionView.reloadData()
let play = SecretShowImgVideoController()
play.imageVideoPath = data[indexPath.row]
self.navigationController?.pushViewController(play, animated: true)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
......@@ -290,6 +300,16 @@ extension SecretViewController : UICollectionViewDelegate,UICollectionViewDataSo
extension SecretViewController : UIImagePickerControllerDelegate , UINavigationControllerDelegate{
private func selectImgVideo(_ row:Int) -> Void {
if selectArray.contains((row)) {
selectArray.remove((row))
}else{
selectArray.add((row))
}
seletedAllBtn.isSelected = selectArray.count == data.count
secretCollect.reloadData()
}
private func SecretPhotos(_ idx:Int, _ data:Any ) -> Void {
if let asset:[PhotoAsset] = data as? [PhotoAsset] {
var assetdels:[PHAsset] = []
......
......@@ -104,7 +104,7 @@ class SecretActionView: UIViewController {
carma.contentHorizontalAlignment = .leading
carma.layer.cornerRadius = 12
carma.tag = 0x10;
carma.setTitle("Instantly Detect Similar Photos", for: .normal)
carma.setTitle("Take photos or videos", for: .normal)
carma.setTitleColor(.black, for: .normal)
carma.addTarget(self, action: #selector(actionTouch(_:)), for: .touchUpInside)
carma.imageEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
......@@ -121,7 +121,7 @@ class SecretActionView: UIViewController {
Photo.contentHorizontalAlignment = .leading
Photo.layer.cornerRadius = 12
Photo.tag = 0x11;
Photo.setTitle("No Ads and Limits", for: .normal)
Photo.setTitle("Import photos or videos", for: .normal)
Photo.setTitleColor(.black, for: .normal)
Photo.addTarget(self, action: #selector(actionTouch(_:)), for: .touchUpInside)
Photo.imageEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
......@@ -132,7 +132,7 @@ class SecretActionView: UIViewController {
lazy var cancelBtn: UIButton = {
let can = UIButton(type: .custom)
can.setTitle("Oldest", for: .normal)
can.setTitle("Cancel", for: .normal)
can.backgroundColor = .white
can.tag = 0x12
can.addTarget(self, action: #selector(actionTouch(_:)), for: .touchUpInside)
......
......@@ -14,7 +14,15 @@ class SecretFirstCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setUI()
backgroundColor = UIColor.random
}
var callback:(()->Void)?
@objc func SelectTouch() -> Void {
guard callback != nil else {
return
}
callback!()
}
private func setUI() -> Void {
......@@ -63,7 +71,7 @@ class SecretFirstCell: UICollectionViewCell {
let info = UIButton(type: .custom)
info.setImage(UIImage(named: "home_info_norl"), for: .normal)
info.setImage(UIImage(named: "home_info_seleted"), for: .selected)
info.isUserInteractionEnabled = false
info.addTarget(self, action: #selector(SelectTouch), for: .touchUpInside)
addSubview(info)
return info
}()
......@@ -75,6 +83,7 @@ class SecretFirstCell: UICollectionViewCell {
private lazy var infoView: UIImageView = {
let info = UIImageView()
info.contentMode = .scaleAspectFill
info.image = UIImage.Clear()
addSubview(info)
return info
}()
......
//
// SecretVideoPlayer.swift
// PhoneManager
//
// Created by edy on 2025/4/3.
//
import UIKit
import AVFoundation
class SecretVideoPlayer: UIView {
private var player: AVPlayer?
var isLooping = false
enum playState {
case start
case playing
case pause
case end
}
var state:playState = .start
override init(frame: CGRect) {
super.init(frame: frame)
setupPlayerLayer()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupPlayerLayer()
}
@objc func tapClick() -> Void {
if state == .pause || state == .start {
resume()
state = .playing
}else if state == .end {
state = .playing
player?.seek(to: CMTime.zero)
resume()
}
else{
state = .pause
pause()
}
}
private func setupPlayerLayer() {
let playerLayer = AVPlayerLayer()
playerLayer.videoGravity = .resizeAspect
layer.addSublayer(playerLayer)
let tap = UITapGestureRecognizer(target: self, action: #selector(tapClick))
self.addGestureRecognizer(tap)
}
override func layoutSubviews() {
super.layoutSubviews()
if let playerLayer = layer.sublayers?.first as? AVPlayerLayer {
playerLayer.frame = bounds
}
}
func playVideo(from url: URL) {
removeObservers()
player = AVPlayer(url: url)
if let playerLayer = layer.sublayers?.first as? AVPlayerLayer {
playerLayer.player = player
}
NotificationCenter.default.addObserver(
self,
selector: #selector(playerItemDidReachEnd),
name: .AVPlayerItemDidPlayToEndTime,
object: player?.currentItem
)
state = .playing
player?.play()
}
// 播放完成回调
@objc private func playerItemDidReachEnd(notification: Notification) {
if isLooping {
player?.seek(to: CMTime.zero)
player?.play()
}
state = .end
}
// 暂停播放
func pause() {
state = .pause
player?.pause()
}
// 继续播放
func resume() {
state = .playing
player?.play()
}
// 移除观察者
private func removeObservers() {
NotificationCenter.default.removeObserver(
self,
name: .AVPlayerItemDidPlayToEndTime,
object: nil
)
}
// 清理资源
deinit {
removeObservers()
}
}
......@@ -8,6 +8,7 @@
import UIKit
import Foundation
import Darwin
import WidgetKit
class WidgetPublicModel: NSObject {
......@@ -19,7 +20,14 @@ class WidgetPublicModel: NSObject {
return batt
}
public class func getDiskSpace() -> (Int64,Int64) {
public class func UseDiskSpace() -> CGFloat {
let disk = getDiskSpace()
let use = disk.0 - disk.1
let useP:CGFloat = CGFloat(use) / CGFloat(disk.0)
return useP
}
private class func getDiskSpace() -> (Int64,Int64) {
let total = TotalDiskSize()
let available = AvailableDiskSize()
return (total,available)
......@@ -49,3 +57,26 @@ class WidgetPublicModel: NSObject {
}
}
class widgetAppgourp: NSObject {
static let share = widgetAppgourp()
func PushWidgetData(_ widget:Int = 0 , battery:Int , storage:Int ) -> Void {
let data = WidgetData(userId: "", widget: widget, battery: battery, widgetStorage: storage)
if let sharedDefaults = UserDefaults(suiteName: "group.com.app.phonemanager") {
let encodedData = try? JSONEncoder().encode(data)
sharedDefaults.set(encodedData, forKey: "widgetSharedData")
}
WidgetCenter.shared.reloadAllTimelines()
}
}
struct WidgetData: Codable {
var userId: String
var widget: Int
var battery: Int
var widgetStorage :Int
}
......@@ -17,9 +17,7 @@ class WidgetBatteryStView: UIView ,BatteryStatusDelegate {
staray.isHidden = true
}else{
widgetT.text = "Storage"
let disk = WidgetPublicModel.getDiskSpace()
let use = disk.0 - disk.1
let useP = Float(use) / Float(disk.0)
let useP = WidgetPublicModel.UseDiskSpace()
widgetR.text = String(format: "%.0f%%", useP * 100)
widgetInfo.image = UIImage(named: "img_storage_widgets")
staray.isHidden = false
......@@ -78,9 +76,7 @@ class WidgetBatteryStView: UIView ,BatteryStatusDelegate {
let end:CGFloat = CGFloat(WidgetPublicModel.battery() / 100.0)
endangle = -Double.pi/2.0 + CGFloat(Double.pi * 2.0 * end)
}else{
let disk = WidgetPublicModel.getDiskSpace()
let use = disk.0 - disk.1
let useP:CGFloat = CGFloat(use) / CGFloat(disk.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),
......
......@@ -34,10 +34,14 @@ class WidgetViewController: BaseViewController {
}
@objc func setWidgetTouch() -> Void {
let battery = WidgetPublicModel.battery()
let storage = WidgetPublicModel.UseDiskSpace() * 100
var widgetIdx = 0
widgetIdx = (widgets == .battery ? 0 : 1) * 10 + widgetMode
widgetAppgourp.share.PushWidgetData(widgetIdx, battery: Int(battery), storage: Int(storage))
alert("Set Widget Successfully")
}
func setUI() -> Void {
titleL.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
......
......@@ -626,13 +626,14 @@ class PhotoAndVideoMananger {
class SecretPhotoManager: NSObject, PhotoPickerControllerDelegate , CameraControllerDelegate {
func cameraController(_ cameraController: HXPhotoPicker.CameraController, didFinishWithResult result: HXPhotoPicker.CameraController.Result, phAsset: PHAsset?, location: CLLocation?) {
switch result {
case .image(let image):
image.compressImage(0.7) {[weak self] image in
let data = image.pngData()
guard callback != nil else { return }
callback!(0,data)
guard self?.callback != nil else { return }
self?.callback!(0,data)
}
break
case .video(let fileUrl):
let data = NSData(contentsOf: fileUrl)
......
......@@ -54,6 +54,16 @@ func weekFormatter() -> String {
return formatter.string(from: Date())
}
func alert(_ msg:String) -> Void {
let alertview = UIAlertController(title: nil, message: msg, preferredStyle: .alert)
guard let root = cWindow?.rootViewController else { return }
root.present(alertview, animated: true)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
alertview.dismiss(animated: true)
}
}
public func Print(_ items: Any...) {
#if DEBUG
......
......@@ -9,6 +9,69 @@ import Foundation
import UIKit
import AVFoundation
extension UIColor {
convenience init(_ hex:UInt32) {
self.init(hex, 1.0)
}
convenience init(_ hex:UInt32 , _ alpha:Float = 1.0) {
let red = Double((hex & 0xff0000) >> 16) / 255.0
let green = Double((hex & 0xff00) >> 8) / 255.0
let blue = Double((hex & 0xff) ) / 255.0
self.init(red: red, green: green, blue: blue, alpha: 1)
}
func generateImage() -> UIImage? {
let size = CGSize(width: 1, height: 1)
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
defer { UIGraphicsEndImageContext() }
self.setFill()
UIRectFill(CGRect(origin: .zero, size: size))
return UIGraphicsGetImageFromCurrentImageContext()
}
}
extension UIImage {
class func Clear(_ color:UIColor = .clear) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
defer { UIGraphicsEndImageContext() }
color.setFill()
UIRectFill(rect)
return UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
}
func compressImage(_ scale: CGFloat , comp:@escaping ((_ image:UIImage)->Void)) -> Void {
DispatchQueue.global().async {
let imageData = self.jpegData(compressionQuality: scale)
guard imageData != nil else {
return
}
let img = UIImage(data: imageData!) ?? UIImage.Clear()
DispatchQueue.main.async {
comp(img)
}
}
}
func resizeAndCompressImage(_ scale: CGFloat = 0.5) -> UIImage {
let size = self.size
let widthRatio = size.width * scale
let heightRatio = size.height * scale
let newSize = CGSize(width: widthRatio, height: heightRatio)
let rect = CGRect(origin: .zero, size: newSize)
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
self.draw(in: rect)
let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resizedImage ?? UIImage.Clear()
}
}
extension String {
// 获取文档路径
......@@ -21,14 +84,17 @@ extension String {
return NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first ?? ""
}
func loadPhotoOrVideo( _ pv:((Float64,UIImage)->Void) ) -> Void {
func loadPhotoOrVideo( _ pv:@escaping ((Float64,UIImage)->Void) ) -> Void {
let path = self.af() + "/SecretIm/"
let abe = path + self
if self.hasSuffix(".png") {
guard let icon = UIImage(contentsOfFile: abe) else {
return pv(-1,UIImage())
pv(-1,UIImage.Clear())
return
}
icon.compressImage(0.5) { image in
pv(-1,image)
}
return pv(-1,icon)
}else{
let url = "SecretIm".document().appendingPathComponent(self)
let asset = AVAsset(url: url)
......@@ -37,12 +103,14 @@ extension String {
let duration = asset.duration
do {
let cgImage = try imageGenerator.copyCGImage(at: CMTime(value: 0, timescale: 1), actualTime: nil)
pv(CMTimeGetSeconds(duration) ,UIImage(cgImage: cgImage))
let icon = UIImage(cgImage: cgImage);
icon.compressImage(0.5) { image in
pv(CMTimeGetSeconds(duration) ,image)
}
} catch {
pv(-1,UIImage() )
}
}
}
}
......@@ -52,7 +120,7 @@ extension URL {
// 获取 路径下所有文件
func directorChildFile() -> [String] {
let fileManager = FileManager.default
let has = fileManager.fileExists(atPath: self.pathExtension )
_ = fileManager.fileExists(atPath: self.pathExtension )
do {
let fileNames = try fileManager.contentsOfDirectory(atPath: self.absoluteString)
var filesOnly: [String] = []
......
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "img_battery_widgets_blue.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "img_battery_widgets_blue@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "img_battery_widgets_blue@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "img_battery_widgets_white.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "img_battery_widgets_white@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "img_battery_widgets_white@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "img_storage_widgets_blue.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "img_storage_widgets_blue@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "img_storage_widgets_blue@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "img_storage_widgets_black.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "img_storage_widgets_black@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "img_storage_widgets_black@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.widgetkit-extension</string>
</dict>
</dict>
</plist>
//
// widget.swift
// widget
//
// Created by edy on 2025/4/3.
//
import WidgetKit
import SwiftUI
struct Provider: TimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), widgets: 0, widgetBattery: 0, widgetStorage: 0)
}
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) {
let entry = loadSharedData()
completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) {
let entry = loadSharedData()
let timeline = Timeline(entries: [entry], policy: .after(Date().addingTimeInterval(120)))
completion(timeline)
}
private func loadSharedData() -> SimpleEntry {
guard let sharedDefaults = UserDefaults(suiteName: "group.com.app.phonemanager"),
let data:Data = sharedDefaults.object(forKey: "widgetSharedData") as? Data,
let decodedData = try? JSONDecoder().decode(WidgetData.self, from: data)
else {
return SimpleEntry(date: Date(), widgets: 0, widgetBattery: 0, widgetStorage: 0)
}
return SimpleEntry(date: Date(), widgets: decodedData.widget, widgetBattery: decodedData.battery, widgetStorage: decodedData.widgetStorage)
}
}
struct WidgetData: Codable {
var userId: String
var widget: Int
var battery: Int
var widgetStorage: Int
}
struct WidgetStyle : Codable {
var textColor : String
var lText : String
var backgound : String
var LineColor : String
var icon : String
var Angle : Double
}
struct SimpleEntry: TimelineEntry {
let date: Date
let widgets:Int
let widgetBattery:Int
let widgetStorage:Int
}
struct BatteryWidgetEntryView : View {
var entry: Provider.Entry
var body: some View {
ZStack {
Color(getwidgetStyle().backgound).ignoresSafeArea()
VStack {
HStack(alignment: .center) {
Text(getwidgetStyle().lText).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topLeading).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle().textColor))
VStack(alignment: .center, spacing: 2) {
Text(String(getwidgetStyle().Angle) + "%" ).frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .topTrailing).font(.system(size: 14)).foregroundColor(Color(getwidgetStyle().textColor))
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))
}
}
}
ZStack {
Image(getwidgetStyle().icon)
ArcShape(startAngle: .degrees(-90), endAngle: .degrees(getwidgetStyle().Angle/100.0 * 360.0 - 90.0), clockwise: false)
.stroke(Color(getwidgetStyle().LineColor), style: StrokeStyle(lineWidth: 5, lineCap: .round) )
}
}.padding(EdgeInsets(top: 16, leading: 10, bottom: 30, trailing: 10))
}
}
func getwidgetStyle() -> WidgetStyle {
var icon = ""
var lt = "Battery"
var anag = 0
if entry.widgets / 10 == 0 {
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))
}
}
struct ArcShape: Shape {
var startAngle: Angle
var endAngle: Angle
var clockwise: Bool
func path(in rect: CGRect) -> Path {
var path = Path()
let center = CGPoint(x: rect.midX, y: rect.midY)
let radius = min(rect.width, rect.height) / 2.0 - 3.0
path.addArc(
center: center,
radius: radius,
startAngle: startAngle,
endAngle: endAngle,
clockwise: clockwise
)
return path
}
}
struct BatteryWidget: Widget {
let kind: String = "BatteryWidget"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
BatteryWidgetEntryView(entry: entry)
}.configurationDisplayName("").description("")
.supportedFamilies([.systemSmall , .systemMedium])
}
}
//
// widgetBundle.swift
// widget
//
// Created by edy on 2025/4/3.
//
import WidgetKit
import SwiftUI
@main
struct widgetBundle: WidgetBundle {
var body: some Widget {
BatteryWidget()
}
}
extension Color {
init(_ hex:String = "FFFFFF") {
let scanner = Scanner(string: hex)
scanner.currentIndex = hex.startIndex
var rgb:UInt64 = 0
scanner.scanHexInt64(&rgb)
let r = Double( (rgb & 0xff0000) >> 16) / 255.0
let g = Double( (rgb & 0xff00) >> 8) / 255.0
let b = Double( (rgb & 0xff)) / 255.0
self.init(red: r, green: g, blue: b)
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.app.phonemanager</string>
</array>
</dict>
</plist>
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