diff --git a/AnimeGen.xcodeproj/project.xcworkspace/xcuserdata/Francesco.xcuserdatad/UserInterfaceState.xcuserstate b/AnimeGen.xcodeproj/project.xcworkspace/xcuserdata/Francesco.xcuserdatad/UserInterfaceState.xcuserstate index a301719e..da13ea8d 100644 Binary files a/AnimeGen.xcodeproj/project.xcworkspace/xcuserdata/Francesco.xcuserdatad/UserInterfaceState.xcuserstate and b/AnimeGen.xcodeproj/project.xcworkspace/xcuserdata/Francesco.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/AnimeGen/APIs Requests/Hmtai/HmtaiSender.swift b/AnimeGen/APIs Requests/Hmtai/HmtaiSender.swift index 103a3941..d0cdc0df 100644 --- a/AnimeGen/APIs Requests/Hmtai/HmtaiSender.swift +++ b/AnimeGen/APIs Requests/Hmtai/HmtaiSender.swift @@ -15,7 +15,7 @@ extension ViewController { let categories3: [String] let endpointPrefix: String - if UserDefaults.standard.bool(forKey: "enableExplicitContent") { + if UserDefaults.standard.bool(forKey: "enableExplictiCont") { categories3 = ["ass", "anal", "bdsm", "classic", "cum", "creampie", "manga", "femdom", "hentai", "incest", "masturbation", "public", "ero", "orgy", "elves", "yuri", "pantsu", "pussy", "glasses", "cuckold", "blowjob", "boobjob", "handjob", "footjob", "boobs", "thighs", "ahegao", "uniform", "gangbang", "tentacles", "gif", "nsfwNeko", "nsfwMobileWallpaper", "zettaiRyouiki"] endpointPrefix = "https://hmtai.hatsunia.cfd/nsfw/" } else { diff --git a/AnimeGen/APIs Requests/kyoko.swift b/AnimeGen/APIs Requests/kyoko.swift index 36c73971..3a23220e 100644 --- a/AnimeGen/APIs Requests/kyoko.swift +++ b/AnimeGen/APIs Requests/kyoko.swift @@ -15,7 +15,7 @@ extension ViewController { let categories: [String] let endpointPrefix: String - if UserDefaults.standard.bool(forKey: "enableExplicitContent") { + if UserDefaults.standard.bool(forKey: "enableExplictiCont") { categories = ["waifu", "neko", "trap", "blowjob"] endpointPrefix = "https://waifu.rei.my.id/nsfw/" } else { diff --git a/AnimeGen/APIs Requests/n-sfw.swift b/AnimeGen/APIs Requests/n-sfw.swift index 600aa714..591851ef 100644 --- a/AnimeGen/APIs Requests/n-sfw.swift +++ b/AnimeGen/APIs Requests/n-sfw.swift @@ -15,7 +15,7 @@ extension ViewController { let categories: [String] let endpointPrefix: String - if UserDefaults.standard.bool(forKey: "enableExplicitContent") { + if UserDefaults.standard.bool(forKey: "enableExplictiCont") { categories = ["anal","ass", "blowjob", "breeding", "buttplug", "cages", "ecchi", "feet", "fo", "furry", "gif", "hentai", "legs", "masturbation", "milf", "muscle", "neko", "paizuri", "petgirls", "pierced", "selfie", "smothering", "socks", "trap", "vagina", "yaoi", "yuri"] endpointPrefix = "https://api.n-sfw.com/nsfw/" } else { diff --git a/AnimeGen/APIs Requests/nekosapi.swift b/AnimeGen/APIs Requests/nekosapi.swift index 41341cb8..20f547cc 100644 --- a/AnimeGen/APIs Requests/nekosapi.swift +++ b/AnimeGen/APIs Requests/nekosapi.swift @@ -14,7 +14,7 @@ extension ViewController { var ratings: [String] = ["safe"] - if UserDefaults.standard.bool(forKey: "enableExplicitContent") { + if UserDefaults.standard.bool(forKey: "enableExplictiCont") { ratings.append("explicit") } diff --git a/AnimeGen/APIs Requests/nekosbot.swift b/AnimeGen/APIs Requests/nekosbot.swift index 2489b984..4fc022b5 100644 --- a/AnimeGen/APIs Requests/nekosbot.swift +++ b/AnimeGen/APIs Requests/nekosbot.swift @@ -15,7 +15,7 @@ extension ViewController { let categories: [String] let endpointPrefix: String - if UserDefaults.standard.bool(forKey: "enableExplicitContent") { + if UserDefaults.standard.bool(forKey: "enableExplictiCont") { categories = ["hentai", "hkitsune", "hanal", "hthigh", "hboobs", "yaoi"] endpointPrefix = "https://nekobot.xyz/api/image?type=" } else { diff --git a/AnimeGen/APIs Requests/pic-re.swift b/AnimeGen/APIs Requests/pic-re.swift index 23e129dd..70dba4bc 100644 --- a/AnimeGen/APIs Requests/pic-re.swift +++ b/AnimeGen/APIs Requests/pic-re.swift @@ -7,84 +7,61 @@ import UIKit -class ImageCache { - private var cache: NSCache = NSCache() - - func image(for url: NSURL) -> UIImage? { - return cache.object(forKey: url) - } - - func insertImage(_ image: UIImage?, for url: NSURL) { - guard let image = image else { return } - cache.setObject(image, forKey: url) - } -} - extension ViewController { - private var imageCache: ImageCache { - return ImageCache() - } - func loadImageFromPicRe() { startLoadingIndicator() - guard let url = URL(string: "https://pic.re/image") else { - print("Invalid URL") - stopLoadingIndicator() - return - } - - let startTime = Date() + let startTime = DispatchTime.now() DispatchQueue.global().async { - self.fetchImageData(from: url, startTime: startTime) - } - } - - private func fetchImageData(from url: URL, startTime: Date) { - if let cachedImage = imageCache.image(for: url as NSURL) { - handleImageLoadingCompletion(with: cachedImage, tags: [], imageUrlString: url.absoluteString, startTime: startTime) - return - } - - var request = URLRequest(url: url) - request.httpMethod = "GET" - - URLSession.shared.dataTask(with: request) { [weak self] (data, response, error) in - guard let self = self else { return } - - if let error = error { - self.handleError("Error: \(error)") + guard let url = URL(string: "https://pic.re/image") else { + print("Invalid URL") + self.stopLoadingIndicator() return } - - guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200, - let imageTagsString = httpResponse.allHeaderFields["image_tags"] as? String, - let imageUrlString = httpResponse.allHeaderFields["image_source"] as? String, - let data = data, let newImage = UIImage(data: data) else { - self.handleError("Invalid HTTP response or data") - return - } - - self.imageCache.insertImage(newImage, for: url as NSURL) - - let tags = imageTagsString.components(separatedBy: ",") - - DispatchQueue.main.async { - self.handleImageLoadingCompletion(with: newImage, tags: tags, imageUrlString: imageUrlString, startTime: startTime) - } - }.resume() - } - - private func handleError(_ message: String) { - print(message) - DispatchQueue.main.async { - self.stopLoadingIndicator() + + var request = URLRequest(url: url) + request.httpMethod = "GET" + + URLSession.shared.dataTask(with: request) { [weak self] (data, response, error) in + guard let self = self else { return } + + if let error = error { + print("Error: \(error)") + self.stopLoadingIndicator() + return + } + + guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { + print("Invalid HTTP response") + self.stopLoadingIndicator() + return + } + + guard let data = data, + let imageTagsString = httpResponse.allHeaderFields["image_tags"] as? String, + let imageUrlString = httpResponse.allHeaderFields["image_source"] as? String, + let newImage = UIImage(data: data) else { + print("Invalid image data or missing response headers") + self.stopLoadingIndicator() + return + } + + let tags = imageTagsString.components(separatedBy: ",") + + DispatchQueue.main.async { + self.handleImageLoadingCompletion(with: newImage, tags: tags, imageUrlString: imageUrlString) + + let endTime = DispatchTime.now() + let executionTime = endTime.uptimeNanoseconds - startTime.uptimeNanoseconds + print("Execution time: \(Double(executionTime) / 1_000_000_000) seconds") + } + }.resume() } } - private func handleImageLoadingCompletion(with newImage: UIImage, tags: [String], imageUrlString: String, startTime: Date) { + private func handleImageLoadingCompletion(with newImage: UIImage, tags: [String], imageUrlString: String) { addImageToHistory(image: newImage, tags: tags) currentImageURL = imageUrlString updateUIWithTags(tags) @@ -94,8 +71,5 @@ extension ViewController { animateImageChange(with: newImage) stopLoadingIndicator() incrementCounter() - - let executionTime = Date().timeIntervalSince(startTime) - print("Execution time: \(executionTime) seconds") } } diff --git a/AnimeGen/APIs Requests/purr.swift b/AnimeGen/APIs Requests/purr.swift index 53a444fa..f8ef0595 100644 --- a/AnimeGen/APIs Requests/purr.swift +++ b/AnimeGen/APIs Requests/purr.swift @@ -15,7 +15,7 @@ extension ViewController { let categories: [String] let endpointPrefix: String - if UserDefaults.standard.bool(forKey: "enableExplicitContent") { + if UserDefaults.standard.bool(forKey: "enableExplictiCont") { categories = ["anal/gif", "blowjob/gif", "cum/gif", "fuck/gif", "neko/gif", "pussylick/gif", "solo/gif", "solo_male/gif", "threesome_fff/gif", "threesome_ffm/gif", "threesome_mmf/gif", "yuri/gif", "neko/img"] endpointPrefix = "https://purrbot.site/api/img/nsfw/" } else { diff --git a/AnimeGen/APIs Requests/waifu-im.swift b/AnimeGen/APIs Requests/waifu-im.swift index d3196320..7cf977d0 100644 --- a/AnimeGen/APIs Requests/waifu-im.swift +++ b/AnimeGen/APIs Requests/waifu-im.swift @@ -12,7 +12,7 @@ extension ViewController { func loadImageFromWaifuIm() { startLoadingIndicator() - let isNSFW = UserDefaults.standard.bool(forKey: "enableExplicitContent") + let isNSFW = UserDefaults.standard.bool(forKey: "enableExplictiCont") let apiEndpoint = "https://api.waifu.im/search" guard var components = URLComponents(string: apiEndpoint) else { diff --git a/AnimeGen/APIs Requests/waifu-it.swift b/AnimeGen/APIs Requests/waifu-it.swift index f2d13007..c4b3f234 100644 --- a/AnimeGen/APIs Requests/waifu-it.swift +++ b/AnimeGen/APIs Requests/waifu-it.swift @@ -15,7 +15,7 @@ extension ViewController { let categories: [String] let endpointPrefix: String = "https://waifu.it/api/v4/" - if UserDefaults.standard.bool(forKey: "enableExplicitContent") { + if UserDefaults.standard.bool(forKey: "enableExplictiCont") { categories = ["angry", "baka", "bite", "blush", "bonk", "bored", "bully", "bye", "chase", "cheer", "cringe", "cry", "dab", "dance", "die", "disgust", "facepalm", "feed", "glomp", "happy", "hi", "highfive", "hold", "hug", "kick", "kill", "kiss", "laugh", "lick", "love", "lurk", "midfing", "nervous", "nom", "nope", "nuzzle", "panic", "pat", "peck", "poke", "pout", "punch", "run", "sad", "shoot", "shrug", "sip", "slap", "sleepy", "smile", "smug", "stab", "stare", "suicide", "tease", "think", "thumbsup", "tickle", "triggered", "wag", "wave", "wink", "yes"] } else { categories = ["angry", "baka", "bite", "blush", "bonk", "bored", "bye", "chase", "cheer", "cringe", "cry", "cuddle", "dab", "dance", "disgust", "facepalm", "feed", "glomp", "happy", "hi", "highfive", "hold", "hug", "kick", "kiss", "laugh", "lurk", "nervous", "nom", "nope", "nuzzle", "panic", "pat", "peck", "poke", "pout", "run", "sad", "shrug", "sip", "slap", "sleepy", "smile", "smug", "stare", "tease", "think", "thumbsup", "tickle", "wag", "wave", "wink", "yes"] diff --git a/AnimeGen/APIs Requests/waifu-pics.swift b/AnimeGen/APIs Requests/waifu-pics.swift index 07d3c345..d850dceb 100644 --- a/AnimeGen/APIs Requests/waifu-pics.swift +++ b/AnimeGen/APIs Requests/waifu-pics.swift @@ -15,7 +15,7 @@ extension ViewController { let categories: [String] let endpointPrefix: String - if UserDefaults.standard.bool(forKey: "enableExplicitContent") { + if UserDefaults.standard.bool(forKey: "enableExplictiCont") { categories = ["waifu", "neko", "trap", "blowjob"] endpointPrefix = "https://api.waifu.pics/nsfw/" } else { @@ -24,6 +24,7 @@ extension ViewController { } let randomCategory = categories.randomElement() ?? "waifu" + let apiEndpoint = "\(endpointPrefix)\(randomCategory)" guard let url = URL(string: apiEndpoint) else { @@ -32,42 +33,36 @@ extension ViewController { return } - let startTime = Date() - - URLSession.shared.dataTask(with: url) { [weak self] (data, response, error) in + let task = URLSession.shared.dataTask(with: url) { (data, response, error) in DispatchQueue.main.async { - guard let self = self else { return } - if let error = error { - self.handleError("Error: \(error)") + print("Error: \(error)") + self.stopLoadingIndicator() return } - guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200, - let data = data, - let jsonResponse = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], - let imageUrlString = jsonResponse["url"] as? String else { - self.handleError("Invalid HTTP response or data") + guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { + print("Invalid HTTP response") + self.stopLoadingIndicator() return } - self.loadImage(with: imageUrlString, tags: [randomCategory], startTime: startTime) + if let data = data, let jsonResponse = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let imageUrlString = jsonResponse["url"] as? String { + self.loadImage(with: imageUrlString, tags: [randomCategory]) + } else { + print("Failed to parse JSON response or missing necessary data.") + self.stopLoadingIndicator() + } } - }.resume() + } + + task.resume() } - private var imageCache: ImageCache { - return ImageCache() - } - - private func loadImage(with imageUrlString: String, tags: [String], startTime: Date) { + private func loadImage(with imageUrlString: String, tags: [String]) { guard let imageUrl = URL(string: imageUrlString) else { - handleError("Invalid image URL") - return - } - - if let cachedImage = imageCache.image(for: imageUrl as NSURL) { - handleImageLoadingCompletion(with: cachedImage, tags: tags, imageUrlString: imageUrlString, startTime: startTime) + print("Invalid image URL") + stopLoadingIndicator() return } @@ -76,34 +71,28 @@ extension ViewController { DispatchQueue.main.async { if imageUrlString.lowercased().hasSuffix(".gif") { if let animatedImage = UIImage.animatedImage(with: UIImage.gifData(data: imageData) ?? [], duration: 1.0) { - self.imageCache.insertImage(animatedImage, for: imageUrl as NSURL) - self.handleImageLoadingCompletion(with: animatedImage, tags: tags, imageUrlString: imageUrlString, startTime: startTime) + self.handleImageLoadingCompletion(with: animatedImage, tags: tags, imageUrlString: imageUrlString) } else { - self.handleError("Failed to create animated image from GIF data.") + print("Failed to create animated image from GIF data.") + self.stopLoadingIndicator() } } else { if let newImage = UIImage(data: imageData) { - self.imageCache.insertImage(newImage, for: imageUrl as NSURL) - self.handleImageLoadingCompletion(with: newImage, tags: tags, imageUrlString: imageUrlString, startTime: startTime) + self.handleImageLoadingCompletion(with: newImage, tags: tags, imageUrlString: imageUrlString) } else { - self.handleError("Failed to load image data.") + print("Failed to load image data.") + self.stopLoadingIndicator() } } } } else { - self.handleError("Failed to load image data.") + print("Failed to load image data.") + self.stopLoadingIndicator() } } } - private func handleError(_ message: String) { - print(message) - DispatchQueue.main.async { - self.stopLoadingIndicator() - } - } - - private func handleImageLoadingCompletion(with newImage: UIImage, tags: [String], imageUrlString: String, startTime: Date) { + private func handleImageLoadingCompletion(with newImage: UIImage, tags: [String], imageUrlString: String) { addImageToHistory(image: newImage, tags: tags) currentImageURL = imageUrlString updateUIWithTags(tags) @@ -113,8 +102,5 @@ extension ViewController { animateImageChange(with: newImage) stopLoadingIndicator() incrementCounter() - - let executionTime = Date().timeIntervalSince(startTime) - print("Execution time: \(executionTime) seconds") } } diff --git a/AnimeGen/AppDelegate.swift b/AnimeGen/AppDelegate.swift index 49da957b..de28abda 100644 --- a/AnimeGen/AppDelegate.swift +++ b/AnimeGen/AppDelegate.swift @@ -9,7 +9,9 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { UserDefaults.standard.register(defaults: ["enableAnimations": true]) @@ -37,14 +39,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - - func applicationWillTerminate(_ application: UIApplication) { - let defaults = UserDefaults.standard - - if defaults.bool(forKey: "disableExplicitContent") { - defaults.set(false, forKey: "enableExplicitContent") - } - } } diff --git a/AnimeGen/Extension/Tags.swift b/AnimeGen/Extension/Tags.swift index 05ec912c..d8dd9de4 100644 --- a/AnimeGen/Extension/Tags.swift +++ b/AnimeGen/Extension/Tags.swift @@ -8,30 +8,30 @@ import UIKit extension ViewController { - + func updateUIWithTags(_ tags: [String], author: String? = nil, category: String? = nil) { - guard UserDefaults.standard.bool(forKey: "enableTags") else { - tagsLabel.attributedText = nil - return - } - - var components = [String]() - - if !tags.isEmpty { - components.append("Tags: \(tags.joined(separator: ", "))") + var tagsString = "" + + if UserDefaults.standard.bool(forKey: "enableTags") && !tags.isEmpty { + tagsString += "Tags: \(tags.joined(separator: ", "))" } - + if let author = author, !author.isEmpty { - components.append("Author: \(author)") + if !tagsString.isEmpty { + tagsString += "\n" + } + tagsString += "Author: \(author)" } - + if let category = category, !category.isEmpty { - components.append("Category: \(category)") + if !tagsString.isEmpty || author != nil && !author!.isEmpty { + tagsString += "\n" + } + tagsString += "Category: \(category)" } - - let tagsString = components.joined(separator: "\n") + let attributedString = NSMutableAttributedString(string: tagsString) - + if !tags.isEmpty { let boldRange = NSRange(location: 0, length: min(5, tagsString.count)) let boldAttributes: [NSAttributedString.Key: Any] = [ @@ -39,23 +39,25 @@ extension ViewController { ] attributedString.addAttributes(boldAttributes, range: boldRange) } - + tagsLabel.attributedText = attributedString } - + + func startLoadingIndicator() { activityIndicator.startAnimating() } - + func stopLoadingIndicator() { activityIndicator.stopAnimating() } - + + func animateFeedback() { guard UserDefaults.standard.bool(forKey: "enableAnimations") else { return } - + UIView.animate(withDuration: 0.3, animations: { self.imageView.transform = CGAffineTransform(scaleX: 1.1, y: 1.1) }) { _ in @@ -64,13 +66,13 @@ extension ViewController { } } } - + func animateImageChange(with newImage: UIImage) { guard UserDefaults.standard.bool(forKey: "enableAnimations") else { imageView.image = newImage return } - + UIView.transition(with: imageView, duration: 0.5, options: .transitionCrossDissolve, animations: { self.imageView.image = newImage }, completion: nil) diff --git a/AnimeGen/Main.storyboard b/AnimeGen/Main.storyboard index 3d0be78b..31b21ae0 100644 --- a/AnimeGen/Main.storyboard +++ b/AnimeGen/Main.storyboard @@ -783,34 +783,6 @@ Display nekos.moe Tags: You can choose whether to show or hide tags sourced from - - - - - - - - - - - - - - - - - - - - - - @@ -822,7 +794,6 @@ Display nekos.moe Tags: You can choose whether to show or hide tags sourced from - @@ -856,10 +827,10 @@ Display nekos.moe Tags: You can choose whether to show or hide tags sourced from - + - + - + - + - + - + - + @@ -937,7 +908,7 @@ Display nekos.moe Tags: You can choose whether to show or hide tags sourced from AnimeGen prioritizes user privacy and does not store any personal data. All generated images are not retained by the app. If a user chooses to save an image, it will only be stored locally in their device's gallery or on the HistoryView. We are committed to ensuring a secure and private experience for our users. - + @@ -958,7 +929,7 @@ Display nekos.moe Tags: You can choose whether to show or hide tags sourced from - + @@ -981,7 +952,7 @@ Display nekos.moe Tags: You can choose whether to show or hide tags sourced from - Copyright © 2023-2024 cranci. All rights reserved. + Copyright © 2023-2024 cranci. All rights reserved. AnimeGen is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -994,10 +965,10 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with AnimeGen. If not, see <https://www.gnu.org/licenses/>. +along with AnimeGen. If not, see <https://www.gnu.org/licenses/>. - + @@ -1018,7 +989,7 @@ along with AnimeGen. If not, see <https://www.gnu.org/licenses/>. - + diff --git a/AnimeGen/Settings/Contents.swift b/AnimeGen/Settings/Contents.swift index d3e98998..b73a1974 100644 --- a/AnimeGen/Settings/Contents.swift +++ b/AnimeGen/Settings/Contents.swift @@ -10,22 +10,16 @@ import UIKit class Contents: UITableViewController { @IBOutlet weak var Contents: UISwitch! - @IBOutlet weak var ContentsRemoval: UISwitch! override func viewDidLoad() { super.viewDidLoad() - Contents.isOn = UserDefaults.standard.bool(forKey: "disableExplicitContent") - ContentsRemoval.isOn = UserDefaults.standard.bool(forKey: "enableExplicitContent") + Contents.isOn = UserDefaults.standard.bool(forKey: "enableExplictiCont") } @IBAction func switchContent(_ sender: UISwitch) { - UserDefaults.standard.set(sender.isOn, forKey: "enableExplicitContent") - } - - @IBAction func switchContentRemove(_ sender: UISwitch) { - UserDefaults.standard.set(sender.isOn, forKey: "disableExplicitContent") + UserDefaults.standard.set(sender.isOn, forKey: "enableExplictiCont") } }