100Years 3 miesięcy temu
rodzic
commit
427ecd5591

+ 58 - 8
TSLiveWallpaper.xcodeproj/project.pbxproj

@@ -74,12 +74,21 @@
 		A83946432D1D701500ABFF0D /* TSLiveWallpaperCopyrightVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83946422D1D701300ABFF0D /* TSLiveWallpaperCopyrightVC.swift */; };
 		A8477C972D22737900DF0B93 /* TSBusinessWebVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8477C962D22737800DF0B93 /* TSBusinessWebVC.swift */; };
 		A8477C992D2291F800DF0B93 /* UserDefault+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8477C982D2291F100DF0B93 /* UserDefault+Ex.swift */; };
+		A8477C9F2D22ABDA00DF0B93 /* TSEditLiveEidtCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8477C9E2D22ABD500DF0B93 /* TSEditLiveEidtCell.swift */; };
 		A84C239A2D1E3A4300B61B55 /* GPVideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A84C23962D1E3A4300B61B55 /* GPVideoPlayerView.swift */; };
 		A84C239B2D1E3A4300B61B55 /* GPVideoClipperController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A84C23982D1E3A4300B61B55 /* GPVideoClipperController.swift */; };
 		A84C239C2D1E3A4300B61B55 /* GPVideoClipperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A84C23972D1E3A4300B61B55 /* GPVideoClipperView.swift */; };
 		A84C239D2D1E3A4300B61B55 /* GPVideoConfigMaker.swift in Sources */ = {isa = PBXBuildFile; fileRef = A84C23952D1E3A4300B61B55 /* GPVideoConfigMaker.swift */; };
 		A84C239F2D1E88CD00B61B55 /* TSFileManagerTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A84C239E2D1E88C500B61B55 /* TSFileManagerTool.swift */; };
 		A858EE172D1CF49B004B680F /* LivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = A858EE162D1CF49B004B680F /* LivePhoto.swift */; };
+		A8C4C01D2D2397B9003C46FC /* UIViewController+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8C4C01C2D2397B4003C46FC /* UIViewController+Ex.swift */; };
+		A8C4C0272D23CD88003C46FC /* AVAssetExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8C4C0202D23CD88003C46FC /* AVAssetExtension.swift */; };
+		A8C4C0282D23CD88003C46FC /* LivePhotoCreater.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8C4C0242D23CD88003C46FC /* LivePhotoCreater.swift */; };
+		A8C4C0292D23CD88003C46FC /* VideoRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8C4C0252D23CD88003C46FC /* VideoRecorder.swift */; };
+		A8C4C02A2D23CD88003C46FC /* Converter4Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8C4C0222D23CD88003C46FC /* Converter4Video.swift */; };
+		A8C4C02B2D23CD88003C46FC /* Converter4Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8C4C0212D23CD88003C46FC /* Converter4Image.swift */; };
+		A8C4C02D2D23D261003C46FC /* metadata.mov in Resources */ = {isa = PBXBuildFile; fileRef = A8C4C02C2D23D261003C46FC /* metadata.mov */; };
+		A8C4C02F2D23DCCC003C46FC /* 1.mov in Resources */ = {isa = PBXBuildFile; fileRef = A8C4C02E2D23DCCC003C46FC /* 1.mov */; };
 		A8E56BF62D1520EC003C54AF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8E56BEC2D1520EC003C54AF /* AppDelegate.swift */; };
 		A8E56BF92D1520EC003C54AF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A8E56BED2D1520EC003C54AF /* Assets.xcassets */; };
 		A8E56BFB2D1520EC003C54AF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A8E56BF02D1520EC003C54AF /* LaunchScreen.storyboard */; };
@@ -158,12 +167,21 @@
 		A83946422D1D701300ABFF0D /* TSLiveWallpaperCopyrightVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSLiveWallpaperCopyrightVC.swift; sourceTree = "<group>"; };
 		A8477C962D22737800DF0B93 /* TSBusinessWebVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSBusinessWebVC.swift; sourceTree = "<group>"; };
 		A8477C982D2291F100DF0B93 /* UserDefault+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefault+Ex.swift"; sourceTree = "<group>"; };
+		A8477C9E2D22ABD500DF0B93 /* TSEditLiveEidtCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSEditLiveEidtCell.swift; sourceTree = "<group>"; };
 		A84C23952D1E3A4300B61B55 /* GPVideoConfigMaker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GPVideoConfigMaker.swift; sourceTree = "<group>"; };
 		A84C23962D1E3A4300B61B55 /* GPVideoPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GPVideoPlayerView.swift; sourceTree = "<group>"; };
 		A84C23972D1E3A4300B61B55 /* GPVideoClipperView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GPVideoClipperView.swift; sourceTree = "<group>"; };
 		A84C23982D1E3A4300B61B55 /* GPVideoClipperController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GPVideoClipperController.swift; sourceTree = "<group>"; };
 		A84C239E2D1E88C500B61B55 /* TSFileManagerTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSFileManagerTool.swift; sourceTree = "<group>"; };
 		A858EE162D1CF49B004B680F /* LivePhoto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LivePhoto.swift; sourceTree = "<group>"; };
+		A8C4C01C2D2397B4003C46FC /* UIViewController+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Ex.swift"; sourceTree = "<group>"; };
+		A8C4C0202D23CD88003C46FC /* AVAssetExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVAssetExtension.swift; sourceTree = "<group>"; };
+		A8C4C0212D23CD88003C46FC /* Converter4Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Converter4Image.swift; sourceTree = "<group>"; };
+		A8C4C0222D23CD88003C46FC /* Converter4Video.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Converter4Video.swift; sourceTree = "<group>"; };
+		A8C4C0242D23CD88003C46FC /* LivePhotoCreater.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LivePhotoCreater.swift; sourceTree = "<group>"; };
+		A8C4C0252D23CD88003C46FC /* VideoRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRecorder.swift; sourceTree = "<group>"; };
+		A8C4C02C2D23D261003C46FC /* metadata.mov */ = {isa = PBXFileReference; lastKnownFileType = video.quicktime; path = metadata.mov; sourceTree = "<group>"; };
+		A8C4C02E2D23DCCC003C46FC /* 1.mov */ = {isa = PBXFileReference; lastKnownFileType = video.quicktime; path = 1.mov; sourceTree = "<group>"; };
 		A8E56BD42D1520DD003C54AF /* TSLiveWallpaper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TSLiveWallpaper.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		A8E56BEC2D1520EC003C54AF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		A8E56BED2D1520EC003C54AF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@@ -245,6 +263,7 @@
 		A81CA4752D15778800A3AAC8 /* Ex */ = {
 			isa = PBXGroup;
 			children = (
+				A8C4C01C2D2397B4003C46FC /* UIViewController+Ex.swift */,
 				A8477C982D2291F100DF0B93 /* UserDefault+Ex.swift */,
 				A81F5B4E2D19673500740085 /* AVAsset+Ex.swift */,
 				A81F5B312D18FA2E00740085 /* Component */,
@@ -367,6 +386,7 @@
 			children = (
 				A83946442D1D7C2B00ABFF0D /* TSEditVideoVC */,
 				A81CA4942D1652B300A3AAC8 /* TSEditLiveVC.swift */,
+				A8477C9E2D22ABD500DF0B93 /* TSEditLiveEidtCell.swift */,
 			);
 			path = TSEditLiveVC;
 			sourceTree = "<group>";
@@ -522,11 +542,34 @@
 		A858EE182D1CF635004B680F /* ThirdParty */ = {
 			isa = PBXGroup;
 			children = (
+				A8C4C0262D23CD88003C46FC /* LivePhoto */,
 				A858EE162D1CF49B004B680F /* LivePhoto.swift */,
 			);
 			path = ThirdParty;
 			sourceTree = "<group>";
 		};
+		A8C4C0232D23CD88003C46FC /* Util */ = {
+			isa = PBXGroup;
+			children = (
+				A8C4C0202D23CD88003C46FC /* AVAssetExtension.swift */,
+				A8C4C0212D23CD88003C46FC /* Converter4Image.swift */,
+				A8C4C0222D23CD88003C46FC /* Converter4Video.swift */,
+			);
+			path = Util;
+			sourceTree = "<group>";
+		};
+		A8C4C0262D23CD88003C46FC /* LivePhoto */ = {
+			isa = PBXGroup;
+			children = (
+				A8C4C0232D23CD88003C46FC /* Util */,
+				A8C4C0242D23CD88003C46FC /* LivePhotoCreater.swift */,
+				A8C4C02C2D23D261003C46FC /* metadata.mov */,
+				A8C4C02E2D23DCCC003C46FC /* 1.mov */,
+				A8C4C0252D23CD88003C46FC /* VideoRecorder.swift */,
+			);
+			path = LivePhoto;
+			sourceTree = "<group>";
+		};
 		A8E56BCB2D1520DD003C54AF = {
 			isa = PBXGroup;
 			children = (
@@ -640,8 +683,10 @@
 			buildActionMask = 2147483647;
 			files = (
 				A8E56BF92D1520EC003C54AF /* Assets.xcassets in Resources */,
+				A8C4C02D2D23D261003C46FC /* metadata.mov in Resources */,
 				A81F5B522D19685900740085 /* response.json in Resources */,
 				A8E56BFB2D1520EC003C54AF /* LaunchScreen.storyboard in Resources */,
+				A8C4C02F2D23DCCC003C46FC /* 1.mov in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -730,11 +775,13 @@
 				A81F5B2B2D18F9C600740085 /* UICollectionView+More.swift in Sources */,
 				A81CA4BA2D16B6E300A3AAC8 /* TSHomeCell.swift in Sources */,
 				A8F778B22D1BA07200BF55D5 /* TSRandomWallpaperBrowseSelectView.swift in Sources */,
+				A8477C9F2D22ABDA00DF0B93 /* TSEditLiveEidtCell.swift in Sources */,
 				A81CA4652D15685F00A3AAC8 /* TSLaunchVC.swift in Sources */,
 				A81F5B402D194EA900740085 /* UIDevice+Extension.swift in Sources */,
 				A8F778AE2D1AC12400BF55D5 /* TSRandomWallpaperBrowseView.swift in Sources */,
 				A81F5B4B2D19658300740085 /* PhotoTools.swift in Sources */,
 				A83946272D1D623800ABFF0D /* TSShareUsVC.swift in Sources */,
+				A8C4C01D2D2397B9003C46FC /* UIViewController+Ex.swift in Sources */,
 				A81F5B542D1969E000740085 /* CGFloat+Ex.swift in Sources */,
 				A81CA48B2D15843700A3AAC8 /* TSCommonTool.swift in Sources */,
 				A81CA4AD2D16944B00A3AAC8 /* TSBaseTabViewCell.swift in Sources */,
@@ -743,6 +790,11 @@
 				A84C239C2D1E3A4300B61B55 /* GPVideoClipperView.swift in Sources */,
 				A84C239D2D1E3A4300B61B55 /* GPVideoConfigMaker.swift in Sources */,
 				A839463C2D1D6E3600ABFF0D /* TSRandomWallpaperCopyrightVC.swift in Sources */,
+				A8C4C0272D23CD88003C46FC /* AVAssetExtension.swift in Sources */,
+				A8C4C0282D23CD88003C46FC /* LivePhotoCreater.swift in Sources */,
+				A8C4C0292D23CD88003C46FC /* VideoRecorder.swift in Sources */,
+				A8C4C02A2D23CD88003C46FC /* Converter4Video.swift in Sources */,
+				A8C4C02B2D23CD88003C46FC /* Converter4Image.swift in Sources */,
 				A81CA4AE2D16944B00A3AAC8 /* TSBaseCollectionCell.swift in Sources */,
 				A81CA4772D15779E00A3AAC8 /* UIColor+Ex.swift in Sources */,
 				A81CA4952D1652B500A3AAC8 /* TSEditLiveVC.swift in Sources */,
@@ -796,18 +848,17 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CODE_SIGN_IDENTITY = "Apple Development";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 2;
+				CURRENT_PROJECT_VERSION = 4;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				ENABLE_APP_SANDBOX = NO;
 				ENABLE_USER_SCRIPT_SANDBOXING = NO;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = TSLiveWallpaper/Info.plist;
-				INFOPLIST_KEY_CFBundleDisplayName = "Live Live";
+				INFOPLIST_KEY_CFBundleDisplayName = LiveLive;
 				INFOPLIST_KEY_NSPhotoLibraryUsageDescription = NSPhotoLibraryUsageDescription;
 				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
 				INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
-				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
-				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
 				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
@@ -831,18 +882,17 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CODE_SIGN_IDENTITY = "Apple Development";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 2;
+				CURRENT_PROJECT_VERSION = 4;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				ENABLE_APP_SANDBOX = NO;
 				ENABLE_USER_SCRIPT_SANDBOXING = NO;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = TSLiveWallpaper/Info.plist;
-				INFOPLIST_KEY_CFBundleDisplayName = "Live Live";
+				INFOPLIST_KEY_CFBundleDisplayName = LiveLive;
 				INFOPLIST_KEY_NSPhotoLibraryUsageDescription = NSPhotoLibraryUsageDescription;
 				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
 				INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
-				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
-				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
 				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",

+ 22 - 0
TSLiveWallpaper/Assets.xcassets/Common/delete_white.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "delete_white@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "delete_white@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
TSLiveWallpaper/Assets.xcassets/Common/delete_white.imageset/delete_white@2x.png


BIN
TSLiveWallpaper/Assets.xcassets/Common/delete_white.imageset/delete_white@3x.png


+ 1 - 40
TSLiveWallpaper/Business/TSBusinessWebVC/TSBusinessWebVC.swift

@@ -44,7 +44,6 @@ class TSBusinessWebVC: TSBaseVC , WKNavigationDelegate {
     override func viewDidLoad() {
         super.viewDidLoad()
         setupWebView()
-        setupProgressView()
         loadURL()
     }
     
@@ -59,21 +58,8 @@ class TSBusinessWebVC: TSBaseVC , WKNavigationDelegate {
             make.edges.equalToSuperview()
         }
 
-        // 添加观察者以监控加载进度
-        webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)
     }
-    
-    private func setupProgressView() {
-        // 初始化进度条
-        progressView = UIProgressView(progressViewStyle: .default)
-        progressView.translatesAutoresizingMaskIntoConstraints = false
-        progressView.progressTintColor = .white.withAlphaComponent(0.5)
-        contentView.addSubview(progressView)
-        progressView.snp.makeConstraints { make in
-            make.edges.equalToSuperview()
-        }
-    }
-    
+
     private func loadURL() {
         guard let url = URL(string: urlType.rawValue) else {
             debugPrint("无效的 URL")
@@ -83,29 +69,4 @@ class TSBusinessWebVC: TSBaseVC , WKNavigationDelegate {
         webView.load(request)
     }
     
-    // 监听加载进度
-    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
-        if keyPath == "estimatedProgress" {
-            progressView.progress = Float(webView.estimatedProgress)
-            progressView.isHidden = webView.estimatedProgress >= 1.0
-        }
-    }
-    
-    deinit {
-        // 移除观察者
-        webView.removeObserver(self, forKeyPath: "estimatedProgress")
-    }
-    
-    // WKNavigationDelegate 方法(可选)
-    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
-        print("开始加载网页")
-    }
-    
-    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
-        print("网页加载完成")
-    }
-    
-    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
-        print("网页加载失败: \(error.localizedDescription)")
-    }
 }

+ 111 - 0
TSLiveWallpaper/Business/TSEditLiveVC/TSEditLiveEidtCell.swift

@@ -0,0 +1,111 @@
+//
+//  TSEditLiveEidtCell.swift
+//  TSLiveWallpaper
+//
+//  Created by 100Years on 2024/12/30.
+//
+
+
+class TSEditLiveSectionModel: CollectionViewSectionComponent{
+    var style:ImageDataStyple = .homeLiveList
+    var items:[TSEditLiveItemModel] = [TSEditLiveItemModel]()
+
+    var sectionInset: UIEdgeInsets {
+        return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
+    }
+    
+    var lineSpacing: CGFloat {
+        return 0
+    }
+    
+    var itemSpacing: CGFloat {
+        return 0
+    }
+    var headerComponent: CollectionViewReuseViewComponent? {
+        return nil
+    }
+    
+    var cells: [CollectionViewCellComponent] {
+        return items
+    }
+
+}
+class TSEditLiveItemModel: CollectionViewCellComponent {
+    var style:ImageDataStyple = .homeLiveList
+    
+    var imageUrl:String = ""
+    var videoUrl:String = ""
+    
+    var cellClass: UICollectionViewCell.Type {
+        return TSEditLiveEidtCell.self
+    }
+    
+    func cellSize(with attrubites: [String : Any]?) -> CGSize {
+        return CGSize(width: k_ScreenWidth, height: 414*kDesignScale)
+    }
+}
+
+
+class TSEditLiveEidtCell : TSBaseCollectionCell , ComponentView{
+    
+    var component:CollectionViewComponent?
+    
+    override func creatUI() {
+        let topEditView = creatTopEditVideoView()
+        bgContentView.addSubview(topEditView)
+        topEditView.snp.makeConstraints { make in
+            make.top.leading.trailing.equalTo(0)
+            make.height.equalTo(414*kDesignScale)
+        }
+    }
+    
+    
+    func creatTopEditVideoView() -> UIView {
+        
+        let bgView = UIView()
+        
+        let videoUpImageView = UIImageView.createImageView(imageName: "video_up")
+        bgView.addSubview(videoUpImageView)
+        videoUpImageView.snp.makeConstraints { make in
+            make.top.equalTo(80)
+            make.centerX.equalToSuperview()
+            make.width.height.equalTo(153)
+        }
+        
+        let videoText = UILabel.createLabel(text: "Upload Video".localized,font: UIFont.systemFont(ofSize: 16, weight: .medium),textColor: .white,textAlignment: .center)
+        bgView.addSubview(videoText)
+        videoText.snp.makeConstraints { make in
+            make.leading.equalTo(16)
+            make.trailing.equalTo(-16)
+            make.top.equalTo(videoUpImageView.snp.bottom).offset(12)
+            make.height.equalTo(16)
+        }
+        
+        let diyBtn: UIButton = TSViewTool.createNormalSubmitBtn(title: "DIY Live Wallpaper".localized, imageNamed: "edit_black") { [weak self]  in
+            guard let self = self else { return }
+  
+            if let component = self.component {
+                if let itemActionHandler = component.itemActionHandler {
+                    itemActionHandler(self, IndexPath(row: 0, section: 0))
+                }
+            }
+        }
+        
+        diyBtn.cornerRadius = 30
+        bgView.addSubview(diyBtn)
+        diyBtn.snp.makeConstraints { make in
+            make.leading.equalTo(16)
+            make.trailing.equalTo(-16)
+            make.top.equalTo(videoText.snp.bottom).offset(53)
+            make.height.equalTo(60)
+        }
+        
+        return bgView
+    }
+    
+    func renderView(with object: Any?, component: CollectionViewComponent, attributes: [String : Any]?) {
+        self.component = component
+    }
+    
+
+}

+ 1 - 1
TSLiveWallpaper/Business/TSHomeVC/TSHomeCell.swift

@@ -38,7 +38,7 @@ class TSHomeCollectionCell : TSBaseCollectionCell ,ComponentView{
     }
 
     func renderView(with object: Any?, component: CollectionViewComponent, attributes: [String : Any]?) {
-        if let itemModel = object as? TSImageDataItemModel, itemModel.imageUrl.contains("http"){
+        if let itemModel = object as? TSImageDataItemModel{
             imageView.setAsyncImage(urlString: itemModel.imageUrl,placeholder: kWapppaperPlaceholderImage,showLoading: true)
         }
     }

+ 2 - 2
TSLiveWallpaper/Business/TSHomeVC/TSHomeVC.swift

@@ -20,8 +20,8 @@ class TSHomeVC : TSBaseVC {
         titleImageView.snp.makeConstraints { make in
             make.centerY.equalToSuperview()
             make.left.equalTo(16)
-            make.width.equalTo(214)
-            make.height.equalTo(24)
+//            make.width.equalTo(214)
+//            make.height.equalTo(24)
         }
 
         return navBarView

+ 65 - 7
TSLiveWallpaper/Business/TSHomeVC/TSLiveWallpaperBrowseVC/EasyVC/TSLiveWallpaperBrowseVC.swift

@@ -30,10 +30,11 @@ class TSLiveWallpaperBrowseVC: TSBaseVC {
             self.btnsAllView.isHidden = isPreview
         }
     }
-    
+//    var itemModels:[TSImageDataItemModel]!
     private var dataModelArray = [TSLiveWallpaperBrowseItemModel]()
     var currentIndex:Int
     init(itemModels: [TSImageDataItemModel],currentIndex:Int) {
+//        self.itemModels = itemModels
         self.currentIndex = currentIndex
         for itemModel in itemModels {
             let model = TSLiveWallpaperBrowseItemModel()
@@ -45,6 +46,15 @@ class TSLiveWallpaperBrowseVC: TSBaseVC {
         super.init()
     }
     
+    var isCanDelete:Bool = false {
+        didSet{
+            deleteBtn.isHidden = !isCanDelete
+            copyrightBtn.isHidden = isCanDelete
+        }
+    }
+    
+    var deleteCompletion:((_ item:Int)->Void)?
+    
     @MainActor required init?(coder: NSCoder) {
         fatalError("init(coder:) has not been implemented")
     }
@@ -77,21 +87,62 @@ class TSLiveWallpaperBrowseVC: TSBaseVC {
         return saveBtn
     }()
     
+    lazy var deleteBtn: UIButton = {//删除按钮
+        let deleteBtn = UIButton.createButton(image: UIImage(named: "delete_white"),backgroundColor: UIColor.fromHex("#111111", alpha: 0.2),corner: 16.0) { [weak self]  in
+            guard let self = self else { return }
+            
+            showCustomAlert(
+                message: "Are you sure to delete".localized,
+                deleteHandler: { [weak self]  in
+                    guard let self = self else { return }
+                    
+                    if let itemModel = self.dataModelArray.safeObj(At: currentIndex) {
+                        self.dataModelArray.remove(at: currentIndex)
+                    }
+                    deleteCompletion?(currentIndex)
+                    
+                    if self.dataModelArray.count == 0 {
+                        self.pop()
+                    }else{
+                        self.collectionView.reloadData()
+                    }
+          
+                },
+                cancelHandler: {
+                   
+                }
+            )
+        }
+        deleteBtn.isHidden = true
+        return deleteBtn
+    }()
     
-    lazy var btnsAllView: UIView = {
-        let btnsAllView = UIView()
-        
+    
+    lazy var copyrightBtn: UIButton = {
         //版权信息按钮
         let copyrightBtn = UIButton.createButton(image: UIImage(named: "info_white"),backgroundColor: UIColor.fromHex("#111111", alpha: 0.2),corner: 16.0) { [weak self]  in
             guard let self = self else { return }
             navigationController?.pushViewController(TSLiveWallpaperCopyrightVC(), animated: true)
         }
+        return copyrightBtn
+    }()
+    
+    lazy var btnsAllView: UIView = {
+        let btnsAllView = UIView()
+        
         btnsAllView.addSubview(copyrightBtn)
         copyrightBtn.snp.makeConstraints { make in
             make.width.height.equalTo(44)
             make.trailing.equalTo(-16)
             make.top.equalTo(topLineH)
         }
+    
+        btnsAllView.addSubview(deleteBtn)
+        deleteBtn.snp.makeConstraints { make in
+            make.width.height.equalTo(44)
+            make.trailing.equalTo(-16)
+            make.top.equalTo(topLineH)
+        }
         
         //预览按钮
         let previewBtn = UIButton.createButton(image: UIImage(named: "random_preview"),backgroundColor: UIColor.fromHex("#000000", alpha: 0.5),corner: 24) { [weak self]  in
@@ -137,6 +188,7 @@ class TSLiveWallpaperBrowseVC: TSBaseVC {
     
     lazy var collectionView: UICollectionView = {
         let collectionView = UICollectionView.createCommon(delegate: self, cellReuseIds: ["TSLiveWallpaperBrowseCell"])
+        collectionView.backgroundColor = .black
         if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
             flowLayout.minimumInteritemSpacing = 0
             flowLayout.minimumLineSpacing = 0
@@ -358,7 +410,9 @@ class TSLiveWallpaperBrowseCell : TSBaseCollectionCell,PHLivePhotoViewDelegate{
     
     var itemModel:TSLiveWallpaperBrowseItemModel? {
         didSet {
-    
+            self.livePhotoView.livePhoto = nil
+            self.livePhotoView.isHidden = true
+            
             if let livePhoto = itemModel?.livePhoto {
                 self.livePhotoView.livePhoto = livePhoto
                 self.livePhotoView.isHidden = false
@@ -387,7 +441,6 @@ class TSLiveWallpaperBrowseCell : TSBaseCollectionCell,PHLivePhotoViewDelegate{
                 
                 
                 group.notify(queue: .main) { [self] in
-                    loading.stopAnimating()
                     
                     if imageCachePath.count == 0 || videoCachePath.count == 0 {
                         return
@@ -396,12 +449,17 @@ class TSLiveWallpaperBrowseCell : TSBaseCollectionCell,PHLivePhotoViewDelegate{
                     let imageCacheUrl = URL(fileURLWithPath: imageCachePath)
                     let videoCacheUrl = URL(fileURLWithPath: videoCachePath)
                     
+                    
+                    if !TSFileManagerTool.fileExists(at: imageCacheUrl) || !TSFileManagerTool.fileExists(at: videoCacheUrl){
+                        return
+                    }
+                    
                     livePhotoTool.generate(from: imageCacheUrl, videoURL: videoCacheUrl, progress: { (percent) in
                         debugPrint(percent)
                     }) { [weak self] (livePhoto, resources) in
                         guard let self = self else { return }
                         
-                        
+                        loading.stopAnimating()
                         itemModel?.livePhoto = livePhoto
                         itemModel?.livePhotoResources = resources
                         

+ 25 - 29
TSLiveWallpaper/Business/TSMineVC/TSMineVC.swift

@@ -7,6 +7,27 @@
 
 class TSMineVC: TSBaseVC, UITableViewDataSource, UITableViewDelegate {
 
+    lazy var tableView:UITableView = {
+        let tableView = UITableView()
+        tableView.initBaseTableView(reuseClass: ["TSMineCell"], isUseMJRefresh: false, delegate: self)
+        return tableView
+    }()
+    
+    lazy var navBarView: TSBaseNavContentBarView = {
+        let navBarView = TSBaseNavContentBarView()
+        let titleImageView = UIImageView.createImageView(imageName: "nav_title_setting",contentMode: .scaleToFill)
+        
+        navBarView.barView.addSubview(titleImageView)
+        titleImageView.snp.makeConstraints { make in
+            make.centerY.equalToSuperview()
+            make.left.equalTo(16)
+//            make.width.equalTo(101)
+//            make.height.equalTo(24)
+        }
+
+        return navBarView
+    }()
+    
     lazy var dataArray:[TSBasicSectionModel] = {
         var dataArray = [TSBasicSectionModel]()
         let sectionModel = TSBasicSectionModel()
@@ -99,41 +120,16 @@ class TSMineVC: TSBaseVC, UITableViewDataSource, UITableViewDelegate {
             height: 80,
             rectCorner:.allCorners,
             tapBlock: {[weak self] itemModel, index, view  in
-                guard let self = self else { return }
-                let vc = TSAboutUsVC()
-                vc.hidesBottomBarWhenPushed = true
-                navigationController?.pushViewController(vc, animated: true)
+//                guard let self = self else { return }
+//                let vc = TSAboutUsVC()
+//                vc.hidesBottomBarWhenPushed = true
+//                navigationController?.pushViewController(vc, animated: true)
             }))
         
         return dataArray
         
     }()
     
-    lazy var tableView:UITableView = {
-        let tableView = UITableView()
-        tableView.initBaseTableView(reuseClass: ["TSMineCell"], isUseMJRefresh: false, delegate: self)
-        return tableView
-    }()
-    
-    lazy var navBarView: TSBaseNavContentBarView = {
-        let navBarView = TSBaseNavContentBarView()
-        let titleImageView = UIImageView.createImageView(imageName: "nav_title_setting",contentMode: .scaleToFill)
-        
-        navBarView.barView.addSubview(titleImageView)
-        titleImageView.snp.makeConstraints { make in
-            make.centerY.equalToSuperview()
-            make.left.equalTo(16)
-            make.width.equalTo(101)
-            make.height.equalTo(24)
-        }
-
-        return navBarView
-    }()
-    
-    override func createData() {
-        
-    }
-    
     override func createView() {
         
         setViewBgImageNamed(named: "view_main_bg")

+ 9 - 8
TSLiveWallpaper/Business/TSRandomWallpaperVC/TSRandomWallpaperVC.swift

@@ -18,8 +18,8 @@ class TSRandomWallpaperVC: TSBaseVC {
         titleImageView.snp.makeConstraints { make in
             make.centerY.equalToSuperview()
             make.left.equalTo(16)
-            make.width.equalTo(185)
-            make.height.equalTo(24)
+//            make.width.equalTo(185)
+//            make.height.equalTo(24)
         }
 
         return navBarView
@@ -31,12 +31,13 @@ class TSRandomWallpaperVC: TSBaseVC {
         cp.collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: k_Height_TabBar, right: 0)
         cp.itemDidSelectedHandler = { [weak self] (object, indexPath) in
             guard let self = self else { return }
-            if indexPath.section == 0 {
-                let tutorialsVC = TSRandomWallpaperTutorialsVC()
-                tutorialsVC.hidesBottomBarWhenPushed = true
-                self.navigationController?.pushViewController(tutorialsVC, animated: true)
-            }else{
-                if let dataModel = object as? TSRandomWallpaperDataItemModel{
+            
+            if let dataModel = object as? TSRandomWallpaperDataItemModel{
+                if dataModel.style == .randomBanner {
+                    let tutorialsVC = TSRandomWallpaperTutorialsVC()
+                    tutorialsVC.hidesBottomBarWhenPushed = true
+                    self.navigationController?.pushViewController(tutorialsVC, animated: true)
+                }else{
                     kPresentModalVC(target: self, modelVC: TSRandomWallpaperBrowseVC(dataModel: dataModel))
                 }
             }

+ 5 - 0
TSLiveWallpaper/Common/Ex/Date+Ex.swift

@@ -16,4 +16,9 @@ extension Date {
     static var hmsString: String {
         return HmsFormatter.string(from: Date())
     }
+    
+    static var timestampString: String {
+        return String(Int(Date().timeIntervalSince1970))
+    }
+
 }

+ 21 - 9
TSLiveWallpaper/Common/Ex/UIImageView+Ex.swift

@@ -66,16 +66,28 @@ extension UIImageView {
             return
         }
         
-        kf.indicatorType = showLoading ? .activity : .none
-        imageView.kf.setImage(with: url,
-             placeholder: placeholder,
-                 options: nil,
-           progressBlock: nil) { result in
+
+        if urlString.contains("http") {
+            kf.indicatorType = showLoading ? .activity : .none
+            imageView.kf.setImage(with: url,
+                 placeholder: placeholder,
+                     options: nil,
+               progressBlock: nil) { result in
+                
+                if let image = try? result.get().image {
+                    completion?(image)
+                }else{
+                    completion?(nil)
+                }
+            }
             
-            if let image = try? result.get().image {
-                completion?(image)
-            }else{
-                completion?(nil)
+        }else if urlString.contains("/") {
+            imageView.image = placeholder
+            imageView.image = UIImage(contentsOfFile: urlString.fillCachePath)
+        }else {
+            imageView.image = placeholder
+            if let image = UIImage(named: urlString) {
+                imageView.image = image
             }
         }
     }

+ 54 - 0
TSLiveWallpaper/Common/Ex/UIViewController+Ex.swift

@@ -0,0 +1,54 @@
+//
+//  UIViewController+Ex.swift
+//  TSLiveWallpaper
+//
+//  Created by 100Years on 2024/12/30.
+//
+
+extension UIViewController {
+    func showCustomAlert(
+        title: String? = "",
+        message: String?,
+        deleteHandler: (() -> Void)? = nil,
+        cancelHandler: (() -> Void)? = nil
+    ) {
+        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
+        
+        // 自定义标题
+        if let title = title {
+            let titleAttributes: [NSAttributedString.Key: Any] = [
+                .font: UIFont.boldSystemFont(ofSize: 20),
+                .foregroundColor: UIColor.white
+            ]
+            let attributedTitle = NSAttributedString(string: title, attributes: titleAttributes)
+            alert.setValue(attributedTitle, forKey: "attributedTitle")
+        }
+        
+        // 自定义消息
+        if let message = message {
+            let messageAttributes: [NSAttributedString.Key: Any] = [
+                .font: UIFont.boldSystemFont(ofSize: 17),
+                .foregroundColor: UIColor.white
+            ]
+            let attributedMessage = NSAttributedString(string: message, attributes: messageAttributes)
+            alert.setValue(attributedMessage, forKey: "attributedMessage")
+        }
+        
+        // 添加按钮
+        let cancelAction = UIAlertAction(title: "Cancel".localized, style: .cancel) { _ in
+            cancelHandler?()
+        }
+        alert.addAction(cancelAction)
+        
+        let deleteAction = UIAlertAction(title: "Delete".localized, style: .destructive) { _ in
+            deleteHandler?()
+        }
+        alert.addAction(deleteAction)
+        
+        // 设置黑暗模式
+        alert.overrideUserInterfaceStyle = .dark
+        
+        // 显示弹窗
+        present(alert, animated: true, completion: nil)
+    }
+}

+ 6 - 0
TSLiveWallpaper/Common/Tool/TSCommonTool/TSCommonTool.swift

@@ -129,6 +129,12 @@ class TSCommonTool {
             return
         }
         
+        
+        if !urlString.contains("http") && urlString.contains("/"){
+            completion(urlString.fillCachePath, nil)
+            return
+        }
+        
         let fileManager = FileManager.default
         
         // 获取缓存目录下的 `cacheVideo` 文件夹路径

+ 93 - 0
TSLiveWallpaper/Common/Tool/TSFileManagerTool.swift

@@ -32,4 +32,97 @@ class TSFileManagerTool {
             debugPrint("文件删除失败: \(error.localizedDescription)")
         }
     }
+    
+    /// 移动文件的方法(自动创建目标文件夹)
+    /// - Parameters:
+    ///   - sourceURL: 文件的源 URL
+    ///   - destinationURL: 目标 URL
+    /// - Throws: 如果移动失败,会抛出错误
+    static func moveFile(from sourceURL: URL, to destinationURL: URL) {
+        let fileManager = FileManager.default
+        
+        // 检查源文件是否存在
+        guard fileManager.fileExists(atPath: sourceURL.path) else {
+            let error = NSError(domain: "FileMoveError", code: 404, userInfo: [NSLocalizedDescriptionKey: "源文件不存在"])
+            debugPrint(error)
+            return
+        }
+        
+        // 获取目标文件夹的路径
+        let destinationDirectory = destinationURL.deletingLastPathComponent()
+        do {
+            // 如果目标文件夹不存在,创建文件夹
+            if !fileManager.fileExists(atPath: destinationDirectory.path) {
+                try fileManager.createDirectory(at: destinationDirectory, withIntermediateDirectories: true, attributes: nil)
+            }
+            
+            // 检查目标路径是否已经存在文件
+            if fileManager.fileExists(atPath: destinationURL.path) {
+                // 如果需要覆盖,可以选择先删除目标文件
+                try fileManager.removeItem(at: destinationURL)
+            }
+            
+            // 尝试移动文件
+            try fileManager.moveItem(at: sourceURL, to: destinationURL)
+        } catch {
+            debugPrint("尝试移动文件失败: \(error.localizedDescription)")
+        }
+    }
+    
+    static func getFileName(from url: URL, includeExtension: Bool = true) -> String {
+        if includeExtension {
+            return url.lastPathComponent
+        } else {
+            return url.deletingPathExtension().lastPathComponent
+        }
+    }
+    
+    
+    
+    /// 获取沙盒 Documents 目录路径
+    static var documentsDirectory: URL {
+        return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
+    }
+
+    /// 获取沙盒 Cache 目录路径
+    static var cacheDirectory: URL {
+        return FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
+    }
+
+    /// 获取沙盒 Temporary 目录路径
+    static var temporaryDirectory: URL {
+        return FileManager.default.temporaryDirectory
+    }
+
+    // MARK: - 文件操作方法
+
+    /// 检查文件或文件夹是否存在
+    static func fileExists(at url: URL) -> Bool {
+        return FileManager.default.fileExists(atPath: url.path)
+    }
+
+    /// 创建文件夹
+    static func createDirectory(at url: URL) throws {
+        if !fileExists(at: url) {
+            try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
+        }
+    }
+    
+    //获取缓存目录下文件夹路径
+    static func getCacheSubPath(at url: URL) ->String? {
+        let array = url.path.components(separatedBy:"/Caches/")
+        let cashFilePath = array.last
+        return cashFilePath
+    }
+    
+}
+
+extension String {
+    var fillCachePath:String{
+        return TSFileManagerTool.cacheDirectory.appendingPathComponent(self).path
+    }
+    
+    var fillCacheURL:URL{
+        return TSFileManagerTool.cacheDirectory.appendingPathComponent(self)
+    }
 }

+ 3 - 0
TSLiveWallpaper/Common/Tool/TSToastTool.swift

@@ -47,4 +47,7 @@ class TSToastTool {
        style.cornerRadius = 8
        return style
     }
+    
+
+    
 }

+ 8 - 2
TSLiveWallpaper/DataManger/TSImageDataCenter.swift

@@ -119,14 +119,20 @@ class TSImageDataCenter{
     
     var editLiveHistoryListArray:[TSImageDataSectionModel]{
         get{
-            if let totalArray = Mapper<TSImageDataSectionModel>().mapArray(JSONString: "historyListJsonString"){
+            if let totalArray = Mapper<TSImageDataSectionModel>().mapArray(JSONString: editLiveHistoryListString){
                 return totalArray
             }else{
-                return [TSImageDataSectionModel()]
+//                let sectionModel = TSImageDataSectionModel()
+//                let itemModel = TSImageDataItemModel()
+//                sectionModel.items = [itemModel]
+//                sectionModel.type = "Historical".localized
+                return []
             }
         }
         
         set{
+            
+            
             if let jsonString = newValue.toJSONString() {
                 editLiveHistoryListString = jsonString
             }