Commit 7f7333dc authored by yqz's avatar yqz

widget 1001

parent aa7e9222
This diff is collapsed.
......@@ -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 {
UserDefaults.standard.set(Secret, forKey: SecretViewController.psKey)
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):
let data = image.pngData()
guard callback != nil else { return }
callback!(0,data)
image.compressImage(0.7) {[weak self] image in
let data = image.pngData()
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] = []
......
......@@ -49,10 +49,10 @@ extension UIColor {
}
static var random: UIColor {
let red = CGFloat.random(in: 0...1)
let green = CGFloat.random(in: 0...1)
let blue = CGFloat.random(in: 0...1)
return UIColor(red: red, green: green, blue: blue, alpha: 1.0)
}
let red = CGFloat.random(in: 0...1)
let green = CGFloat.random(in: 0...1)
let blue = CGFloat.random(in: 0...1)
return UIColor(red: red, green: green, blue: blue, alpha: 1.0)
}
}
{
"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