浏览代码

first commit

Kan1aSorata 2 年之前
父节点
当前提交
f1c5565661

+ 18 - 6
AIPaint.xcodeproj/project.pbxproj

@@ -53,6 +53,7 @@
 		A0E657FD160CDE6681C310A2 /* Pods_AIPaint.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AIPaint.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		AFB71330BC45DD1A91668D6A /* Pods-AIPaint.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AIPaint.debug.xcconfig"; path = "Target Support Files/Pods-AIPaint/Pods-AIPaint.debug.xcconfig"; sourceTree = "<group>"; };
 		C08447441CAFA1A2EAF6458F /* Pods-AIPaint-AIPaintUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AIPaint-AIPaintUITests.debug.xcconfig"; path = "Target Support Files/Pods-AIPaint-AIPaintUITests/Pods-AIPaint-AIPaintUITests.debug.xcconfig"; sourceTree = "<group>"; };
+		FA38329C293F16EA005B59D7 /* AIPaint.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AIPaint.entitlements; sourceTree = "<group>"; };
 		FADEA46D2936102A00F1743C /* AIPaint.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AIPaint.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		FADEA4702936102A00F1743C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		FADEA4772936102A00F1743C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
@@ -149,6 +150,7 @@
 		FADEA46F2936102A00F1743C /* AIPaint */ = {
 			isa = PBXGroup;
 			children = (
+				FA38329C293F16EA005B59D7 /* AIPaint.entitlements */,
 				FAEAEB672938ED4700C1D1E6 /* View */,
 				FADEA4AC2936630700F1743C /* Model */,
 				FADEA4762936102A00F1743C /* Main.storyboard */,
@@ -628,16 +630,21 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				CODE_SIGN_ENTITLEMENTS = AIPaint/AIPaint.entitlements;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = VVA64747UZ;
+				CURRENT_PROJECT_VERSION = 3;
+				DEVELOPMENT_TEAM = 257T642AW2;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIPaint/Info.plist;
+				INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment";
+				INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "Access your photo library to save pictures.";
+				INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "Access your photo library to save pictures.";
 				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
 				INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
 				INFOPLIST_KEY_UIMainStoryboardFile = Main;
 				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
 				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				IPHONEOS_DEPLOYMENT_TARGET = 15.0;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
 					"@executable_path/Frameworks",
@@ -651,7 +658,7 @@
 					"\"SwiftyJSON\"",
 					"-ObjC",
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = fengyuhe.AIPaint;
+				PRODUCT_BUNDLE_IDENTIFIER = org.hefengyu.huajiang;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_EMIT_LOC_STRINGS = YES;
 				SWIFT_VERSION = 5.0;
@@ -665,16 +672,21 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				CODE_SIGN_ENTITLEMENTS = AIPaint/AIPaint.entitlements;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = VVA64747UZ;
+				CURRENT_PROJECT_VERSION = 3;
+				DEVELOPMENT_TEAM = 257T642AW2;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIPaint/Info.plist;
+				INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment";
+				INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "Access your photo library to save pictures.";
+				INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "Access your photo library to save pictures.";
 				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
 				INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
 				INFOPLIST_KEY_UIMainStoryboardFile = Main;
 				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
 				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				IPHONEOS_DEPLOYMENT_TARGET = 15.0;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
 					"@executable_path/Frameworks",
@@ -688,7 +700,7 @@
 					"\"SwiftyJSON\"",
 					"-ObjC",
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = fengyuhe.AIPaint;
+				PRODUCT_BUNDLE_IDENTIFIER = org.hefengyu.huajiang;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_EMIT_LOC_STRINGS = YES;
 				SWIFT_VERSION = 5.0;

+ 68 - 4
AIPaint.xcworkspace/xcuserdata/fengyuhe.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -14,8 +14,8 @@
             filePath = "AIPaint/HomeViewController.swift"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "37"
-            endingLineNumber = "37"
+            startingLineNumber = "40"
+            endingLineNumber = "40"
             landmarkName = "viewDidLoad()"
             landmarkType = "7">
          </BreakpointContent>
@@ -30,11 +30,75 @@
             filePath = "AIPaint/HomeViewController.swift"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "36"
-            endingLineNumber = "36"
+            startingLineNumber = "39"
+            endingLineNumber = "39"
             landmarkName = "viewDidLoad()"
             landmarkType = "7">
          </BreakpointContent>
       </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "9FEB4DD1-EB1C-464E-A75C-10EA4592FDA2"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AIPaint/DrawViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "181"
+            endingLineNumber = "181"
+            landmarkName = "translatePrompt(prompt:negativePrompt:completion:)"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "8D28765F-7E6D-4C05-A364-F3C325E19923"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AIPaint/DrawViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "182"
+            endingLineNumber = "182"
+            landmarkName = "translatePrompt(prompt:negativePrompt:completion:)"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "C1BC68B1-DD7E-47A5-A61A-96E3CBBDB4C8"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AIPaint/HomeViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "57"
+            endingLineNumber = "57"
+            landmarkName = "viewWillAppear(_:)"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "F6E63C2B-76CD-49F6-BDCD-A27D06CB9ED0"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AIPaint/HomeViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "58"
+            endingLineNumber = "58"
+            landmarkName = "viewWillAppear(_:)"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
    </Breakpoints>
 </Bucket>

+ 10 - 0
AIPaint/AIPaint.entitlements

@@ -0,0 +1,10 @@
+<?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.developer.applesignin</key>
+	<array>
+		<string>Default</string>
+	</array>
+</dict>
+</plist>

二进制
AIPaint/Assets.xcassets/404.imageset/404 1.jpeg


二进制
AIPaint/Assets.xcassets/404.imageset/404 2.jpeg


+ 2 - 0
AIPaint/Assets.xcassets/404.imageset/Contents.json

@@ -6,10 +6,12 @@
       "scale" : "1x"
     },
     {
+      "filename" : "404 1.jpeg",
       "idiom" : "universal",
       "scale" : "2x"
     },
     {
+      "filename" : "404 2.jpeg",
       "idiom" : "universal",
       "scale" : "3x"
     }

二进制
AIPaint/Assets.xcassets/AppIcon.appiconset/AppIcon.jpeg


+ 1 - 0
AIPaint/Assets.xcassets/AppIcon.appiconset/Contents.json

@@ -1,6 +1,7 @@
 {
   "images" : [
     {
+      "filename" : "AppIcon.jpeg",
       "idiom" : "universal",
       "platform" : "ios",
       "size" : "1024x1024"

+ 135 - 70
AIPaint/DrawViewController.swift

@@ -57,6 +57,14 @@ class DrawViewController: UIViewController {
         return imageView
     }()
     
+    lazy var remindText: UILabel = {
+        var label = UILabel()
+        label.text = "长按图片进行保存"
+        label.textColor = .systemGray5
+        label.textAlignment = .center
+        return label
+    }()
+    
     var prompt = ""
     var tranPrompt = ""
     var negativePrompt = ""
@@ -70,17 +78,20 @@ class DrawViewController: UIViewController {
     override func viewDidLoad() {
         super.viewDidLoad()
         
-        view.backgroundColor = .white
+        if UITraitCollection.current.userInterfaceStyle == .dark {
+            view.backgroundColor = .black
+        } else {
+            view.backgroundColor = .white
+        }
+    
         self.title = "AI Paint"
-        
         delegate = UIApplication.shared.delegate as? AppDelegate
-        context = delegate!.persistentContainer.viewContext
-        painting = NSEntityDescription.insertNewObject(forEntityName: "Painting", into: context!) as? Painting
 
         view.addSubview(generateView)
         generateView.addSubview(promptTextField)
         generateView.addSubview(negativePromptTextField)
         generateView.addSubview(generateButton)
+        view.addSubview(remindText)
         
         view.addSubview(generateImage)
         longPress = UILongPressGestureRecognizer(target: self, action: #selector(saveImageToPhotos))
@@ -120,16 +131,23 @@ class DrawViewController: UIViewController {
             make.height.equalTo(view.safeAreaLayoutGuide.snp.height).multipliedBy(0.60)
             make.centerX.equalTo(view.safeAreaLayoutGuide.snp.centerX)
         }
+        
+        remindText.snp.makeConstraints { (make) in
+            make.top.equalTo(generateImage.snp.top).offset(2)
+            make.width.equalTo(generateImage.snp.width)
+            make.height.equalTo(generateImage.snp.height).multipliedBy(0.40)
+            make.centerX.equalTo(generateImage.snp.centerX)
+        }
     }
     
-    func translatePrompt(prompt: String, negativePrompt: String) -> (tranPrompt: String, tranNegativePrompt: String){
+    func translatePrompt(prompt: String, negativePrompt: String, completion: @escaping (_ tranPrompt: String, _ tranNegativePrompt: String) -> Void) {
         let APP_KEY = "3bb96f14d2af67ec"
         let APP_SECRET = "SRQF1jGwAMuYciFK33KfyRGKa7B1x38u"
         let q = prompt + "|" + negativePrompt
         let salt = UUID().uuidString
         let curtime = Int(Date().timeIntervalSince1970)
-        print(curtime)
-        let signStr = APP_KEY + q + salt + String(curtime) + APP_SECRET
+        let inputQ = q.count <= 20 ? q : String(q.prefix(10)) + String(q.count) + String(q.suffix(10))
+        let signStr = APP_KEY + inputQ + salt + String(curtime) + APP_SECRET
         let cryptoSign = signStr.sha256
         let paramDic = ["q": q, "from": "auto", "to": "en", "appKey": APP_KEY, "salt": salt, "sign": cryptoSign, "signType": "v3", "curtime": String(curtime)]
         let list  = NSMutableArray()
@@ -139,9 +157,16 @@ class DrawViewController: UIViewController {
         }
         let paramStr = list.componentsJoined(by: "&")
         let paramData = "https://openapi.youdao.com/api?" + paramStr
-        var addr = paramData.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
-        let url = URL(string: addr!)
-        var request = URLRequest(url: url!)
+        print(paramData)
+        guard let addr = paramData.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
+            print("error")
+            return
+        }
+        guard let url = URL(string: addr) else {
+            print("error")
+            return
+        }
+        var request = URLRequest(url: url)
         request.httpMethod = "GET"
         
         var promptValue = ""
@@ -149,88 +174,119 @@ class DrawViewController: UIViewController {
         
         let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
             do {
-                let jsonData = try JSON(data: data!)
+                guard let unwrapedData = data else {
+                    print("error")
+                    return
+                }
+                let jsonData = try JSON(data: unwrapedData)
                 let promptData = jsonData["translation"][0].stringValue
                 print(promptData)
-                if String(promptData.first!) == "|" {
-                    let subStringArr = promptData.split(separator: "| ")
-                    negativePromotValue = String(subStringArr[0])
+                if String(promptData.first ?? String.Element("")) == "|" {
+                    if #available(iOS 16.0, *) {
+                        let subStringArr = promptData.split(separator: "|")
+                        negativePromotValue = String(subStringArr[0])
+                    } else {
+                        // Fallback on earlier versions
+                        let subStringArr = promptData.components(separatedBy: "|")
+                        negativePromotValue = String(subStringArr[0])
+                    }
                     
-                } else if String(promptData.last!) == "|" {
-                    let subStringArr = promptData.split(separator: " |")
-                    promptValue = String(subStringArr[0])
+                } else if String(promptData.last ?? String.Element("")) == "|" {
+                    if #available(iOS 16.0, *) {
+                        let subStringArr = promptData.split(separator: " |")
+                        promptValue = String(subStringArr[0])
+                    } else {
+                        // Fallback on earlier versions
+                        let subStringArr = promptData.components(separatedBy: "|")
+                        promptValue = String(subStringArr[0])
+                    }
+                } else if promptData == "|"{
+                    // do nothing
                 } else {
-                    let subStringArr = promptData.split(separator: " | ")
-                    promptValue = String(subStringArr[0])
-                    negativePromotValue = String(subStringArr[1])
+                    if #available(iOS 16.0, *) {
+                        let subStringArr = promptData.split(separator: "|")
+                        promptValue = String(subStringArr[0])
+                        negativePromotValue = String(subStringArr[1])
+                    } else {
+                        // Fallback on earlier versions
+                        let subStringArr = promptData.components(separatedBy: "|")
+                        promptValue = String(subStringArr[0])
+                        negativePromotValue = String(subStringArr[1])
+                    }
+                    
                 }
             } catch {}
+            completion(promptValue, negativePromotValue)
         }
         task.resume()
-        return (promptValue, negativePromotValue)
     }
     
     @objc func generateAction() {
-        let translation = translatePrompt(prompt: promptTextField.text!, negativePrompt: negativePromptTextField.text!)
-        generateButton.backgroundColor = .gray
-        generateButton.isUserInteractionEnabled = false
-        
-        print("translation", translation)
-        var promptValue = translation.tranPrompt
-        var negativePromotValue = translation.tranNegativePrompt
-        
-        print("Generation: \(promptValue) + \(negativePromotValue)")
-        
-        prompt = "masterpiece, best quality, " + promptValue
-        negativePrompt = "lowres, bad anatomy, bad hands, text, error, missing fingers, extra digits, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, bad feet, " + negativePromotValue
-        sessionHash = UUID().uuidString
-        painting?.prompt = promptTextField.text!
-        painting?.negative_prompt = negativePromptTextField.text!
-        painting?.session_hash = sessionHash
-        painting?.create_time = Date()
-        let url = URL(string: "https://aipaint.hefengyu.org/api/predict/")
-        var request = URLRequest(url: url!)
-        request.httpMethod = "POST"
-        let postData: [String: Any] = ["fn_index":50,"data":[prompt,negativePrompt,"None","None",20,"Euler a",false,false,1,1,7,-1,-1,0,0,0,false,512,512,false,0.7,0,0,"None",false,false,false,"","Seed","","Nothing","",true,false,false,"null","",""],"session_hash":sessionHash]
-        let jsonData = try? JSONSerialization.data(withJSONObject: postData, options: [])
-        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
-        request.httpBody = jsonData
-        var imageData: Data?
-        let dataTask = URLSession.shared.dataTask(with: request) { (data, request, error) in
-            do {
-                let json = try? JSON(data: data!)
-                let imageAddr = json!["data"][0][0]["name"].stringValue
-                let addrProcess = imageAddr.replacingOccurrences(of: "\\", with: "/")
-                let imageStr = "https://aipaint.hefengyu.org/file=\(addrProcess)"
-                let imageUrl = URL(string: imageStr)
-                imageData = try? Data(contentsOf: imageUrl!)
-                DispatchQueue.main.async { [self] in
-                    painting?.image = imageData!
-                    self.generateImage.image = UIImage(data: imageData!)
-                    self.generateButton.backgroundColor = .blue
-                    self.generateButton.isUserInteractionEnabled = true
-                    if context!.hasChanges {
-                        do {
-                            try context?.save()
-                            print("save success.")
-                        } catch {}
+        let promptText = promptTextField.text ?? ""
+        let negativePromptText = negativePromptTextField.text ?? ""
+
+        translatePrompt(prompt: promptTextField.text!, negativePrompt: negativePromptTextField.text!) { [self] promptValue, negativePromotValue in
+            
+            prompt = "masterpiece, best quality, " + promptValue
+            negativePrompt = "lowres, bad anatomy, bad hands, text, error, missing fingers, extra digits, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, bad feet, " + negativePromotValue
+            sessionHash = UUID().uuidString
+            guard let unwrapedDelegate = delegate else {
+                return
+            }
+            context = unwrapedDelegate.persistentContainer.viewContext
+            painting = NSEntityDescription.insertNewObject(forEntityName: "Painting", into: context!) as? Painting
+            painting?.prompt = promptText
+            painting?.negative_prompt = negativePromptText
+            painting?.session_hash = sessionHash
+            painting?.create_time = Date()
+            guard let url = URL(string: "https://aipaint.hefengyu.org/api/predict/") else {
+                print("error")
+                return
+            }
+            var request = URLRequest(url: url)
+            request.httpMethod = "POST"
+            let postData: [String: Any] = ["fn_index":50, "data":[prompt,negativePrompt,"None","None",20,"Euler a",false,false,1,1,7,-1,-1,0,0,0,false,512,512,false,0.7,0,0,"None",false,false,false,"","Seed","","Nothing","",true,false,false,"null","",""], "session_hash":sessionHash]
+            let jsonData = try? JSONSerialization.data(withJSONObject: postData, options: [])
+            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
+            request.httpBody = jsonData
+            let dataTask = URLSession.shared.dataTask(with: request) { (data, request, error) in
+                do {
+                    guard let data = data else {
+                        return
+                    }
+                    guard let json = try? JSON(data: data) else {
+                        return
+                    }
+                    let imageAddr = json["data"][0][0]["name"].stringValue
+                    let addrProcess = imageAddr.replacingOccurrences(of: "\\", with: "/")
+                    let imageStr = "https://aipaint.hefengyu.org/file=\(addrProcess)"
+                    guard let imageUrl = URL(string: imageStr) else {
+                        return
+                    }
+                    guard let imageData = try? Data(contentsOf: imageUrl) else {
+                        return
+                    }
+                    DispatchQueue.main.async { [self] in
+                        painting?.image = imageData
+                        self.generateImage.image = UIImage(data: imageData)
+                        self.generateButton.backgroundColor = .blue
+                        self.generateButton.isUserInteractionEnabled = true
+                        saveContext()
                     }
                 }
             }
+            dataTask.resume()
         }
-//        let processURL = URL(string: "https://aipaint.hefengyu.org/api/predict/")
-//        let processTask = URLSession.shared.dataTask(with: <#T##URLRequest#>)
-        dataTask.resume()
+        generateButton.backgroundColor = .gray
+        generateButton.isUserInteractionEnabled = false
     }
     
     @objc func saveImageToPhotos() {
         if (longPress!.state == .began) {
-            // do something
-            print("nice")
             guard let img = generateImage.image else {
+                print("error")
                 return
             }
-            
             switch PHPhotoLibrary.authorizationStatus() {
             case .authorized:
                 saveImg(image: img)
@@ -258,6 +314,15 @@ class DrawViewController: UIViewController {
         }
     }
     
+    func saveContext() {
+        if context!.hasChanges {
+            do {
+                try context?.save()
+                print("save success.")
+            } catch {}
+        }
+    }
+    
     func saveImg(image: UIImage) {
         PHPhotoLibrary.shared().performChanges({
             PHAssetChangeRequest.creationRequestForAsset(from: image)

+ 15 - 10
AIPaint/HomeViewController.swift

@@ -22,14 +22,17 @@ class HomeViewController: UIViewController, UITableViewDelegate, UITableViewData
 
     var delegate: AppDelegate?
     var context: NSManagedObjectContext?
-    var painting: Painting?
     var fetchPainting: NSFetchRequest<Painting>?
     var info: [Painting] = []
     
     override func viewDidLoad() {
         super.viewDidLoad()
         
-        view.backgroundColor = .white
+        if UITraitCollection.current.userInterfaceStyle == .dark {
+            view.backgroundColor = .black
+        } else {
+            view.backgroundColor = .white
+        }
         self.title = "作品"
         
         delegate = UIApplication.shared.delegate as? AppDelegate
@@ -38,7 +41,6 @@ class HomeViewController: UIViewController, UITableViewDelegate, UITableViewData
         
         paintingTableView.delegate = self
         paintingTableView.dataSource = self
-//        paintingTableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
         view.addSubview(paintingTableView)
         
         paintingTableView.snp.makeConstraints { (make) in
@@ -47,22 +49,23 @@ class HomeViewController: UIViewController, UITableViewDelegate, UITableViewData
             make.height.equalTo(view.safeAreaLayoutGuide.snp.height)
             make.centerX.equalTo(view.safeAreaLayoutGuide.snp.centerX)
         }
-        
+    }
+    
+    override func viewWillAppear(_ animated: Bool) {
         do {
             let paintings = try context?.fetch(fetchPainting!)
             for painting in paintings! {
-                info.append(painting)
+                if !info.contains(painting) {
+                    info.append(painting)
+                } else {
+                }
             }
         } catch {}
-        
-    }
-    
-    override func viewWillAppear(_ animated: Bool) {
-
         paintingTableView.reloadData()
     }
     
     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        print("info loaded \(info.count)")
         return info.count
     }
     
@@ -72,6 +75,8 @@ class HomeViewController: UIViewController, UITableViewDelegate, UITableViewData
         return cell
     }
     
+    
+    
     func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
         return 100
     }

+ 2 - 4
AIPaint/Info.plist

@@ -2,9 +2,7 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
-	<key>NSPhotoLibraryUsageDescription</key>
-	<string>Access your photo library to save pictures.</string>
-	<key>NSPhotoLibraryAddUsageDescription</key>
-	<string>Access your photo library to save pictures.</string>
+	<key>CFBundleIconName</key>
+	<string>AppIcon</string>
 </dict>
 </plist>

+ 76 - 3
AIPaint/SettingsViewController.swift

@@ -7,30 +7,103 @@
 
 import UIKit
 import SnapKit
+import AuthenticationServices
 
 class SettingsViewController: UIViewController {
     
     let welcomeView: UIView = {
         var view = UIView()
         view.layer.borderWidth = 1
-        view.layer.borderColor = UIColor.black.cgColor
+        view.layer.borderColor = UIColor.systemGray.cgColor
         view.layer.cornerRadius = 14
         return view
     }()
     
+    lazy var welcomeText: UILabel = {
+        var label = UILabel()
+        label.numberOfLines = 0
+        label.lineBreakMode = .byWordWrapping
+        label.text = "感谢你参与画酱的封闭测试,见证画酱的诞生!\n你可以加入QQ群来对本 App 提出宝贵意见:390674039 \n此 App 目前还在初期稳定行测试阶段,如果你有什么功能上的需求,或是对于 App 的设计有任何的建议,欢迎进群与我讨论!\n \n暂时还没适配暗黑模式,请在正常模式使用此 App。"
+        return label
+    }()
+    
+    var signInWithAppleButton = ASAuthorizationAppleIDButton(authorizationButtonType: .default, authorizationButtonStyle: .black)
+    
     override func viewDidLoad() {
         super.viewDidLoad()
         
-        view.backgroundColor = .white
+        if UITraitCollection.current.userInterfaceStyle == .dark {
+            view.backgroundColor = .black
+        } else {
+            view.backgroundColor = .white
+        }
         self.title = "设置"
+
+        signInWithAppleButton.cornerRadius = 8.0
+        signInWithAppleButton.addTarget(self, action: #selector(loginButtonTapped), for: .touchUpInside)
+        view.addSubview(signInWithAppleButton)
+        
+        if #available(iOS 15.0, *) {
+            signInWithAppleButton.isHidden = false
+        } else {
+            signInWithAppleButton.isHidden = true
+        }
         
         view.addSubview(welcomeView)
+        welcomeView.addSubview(welcomeText)
         
         welcomeView.snp.makeConstraints { (make) in
             make.top.equalTo(view.safeAreaLayoutGuide.snp.top).offset(5)
             make.centerX.equalTo(view.safeAreaLayoutGuide.snp.centerX)
             make.width.equalTo(view.safeAreaLayoutGuide.snp.width).multipliedBy(0.95)
-            make.height.equalTo(view.safeAreaLayoutGuide.snp.height)
+            make.height.equalTo(view.safeAreaLayoutGuide.snp.height).multipliedBy(0.35)
+        }
+        
+        welcomeText.snp.makeConstraints { (make) in
+            make.top.equalTo(welcomeView.snp.top).offset(5)
+            make.centerX.equalTo(welcomeView.snp.centerX)
+            make.width.equalTo(welcomeView.snp.width).multipliedBy(0.9)
+            make.height.equalTo(welcomeView.snp.height).multipliedBy(0.98)
+        }
+    }
+    
+    @objc func loginButtonTapped() {
+        if #available(iOS 15.0, *) {
+            let provider = ASAuthorizationAppleIDProvider()
+            let request = provider.createRequest()
+            request.requestedScopes = [.email, .fullName]
+            let controller = ASAuthorizationController(authorizationRequests: [request])
+            controller.delegate = self
+//            controller.presentationContextProvider = self
+            controller.performRequests()
         }
     }
 }
+
+extension SettingsViewController: ASAuthorizationControllerDelegate {
+    @available(iOS 15.0, *)
+    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
+        do {
+            //苹果用户唯一标识符,该值在同一个开发者账号下的所有 App 下是一样的,开发者可以用该唯一标识符与自己后台系统的账号体系绑定起来。
+            var credential = authorization.credential as! ASAuthorizationAppleIDCredential
+            let userID = credential.user
+            let fullName = credential.fullName
+            let identifierToken = credential.identityToken
+        }
+        
+        
+        func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
+            print("Login Error")
+        }
+        
+        func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
+            return view.window!
+        }
+    }
+}
+
+//extension SettingsViewController: ASAuthorizationControllerPresentationContextProviding {
+//    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
+//
+//    }
+//}

+ 4 - 4
AIPaint/View/PaintingCell.swift

@@ -31,7 +31,7 @@ class PaintingCell: UITableViewCell {
             var label = UILabel()
             label.font = UIFont.systemFont(ofSize: 15)
             label.textAlignment = .left
-            label.textColor = .black
+            label.textColor = .systemGray2
             return label
         }()
         
@@ -39,7 +39,7 @@ class PaintingCell: UITableViewCell {
             var label = UILabel()
             label.font = UIFont.systemFont(ofSize: 15)
             label.textAlignment = .left
-            label.textColor = .black
+            label.textColor = .systemGray2
             return label
         }()
         
@@ -47,7 +47,7 @@ class PaintingCell: UITableViewCell {
             var label = UILabel()
             label.font = UIFont.systemFont(ofSize: 15)
             label.textAlignment = .left
-            label.textColor = .black
+            label.textColor = .systemGray2
             return label
         }()
         
@@ -55,7 +55,7 @@ class PaintingCell: UITableViewCell {
             var label = UILabel()
             label.font = UIFont.systemFont(ofSize: 15)
             label.textAlignment = .left
-            label.textColor = .black
+            label.textColor = .systemGray2
             return label
         }()
         

+ 7 - 0
AIPaint/extension.swift

@@ -13,4 +13,11 @@ extension String {
         CC_SHA256(utf8, CC_LONG(utf8!.count - 1), &digest)
         return digest.reduce("") { $0 + String(format:"%02x", $1) }
     }
+    
+    func encodeBase64() -> String {
+        if let data = self.data(using: .utf8) {
+            return data.base64EncodedString()
+        }
+        return ""
+    }
 }