From 1b8daa59c09d5e609373bb774b6211cec66339b6 Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Thu, 7 Dec 2023 18:04:48 -0600 Subject: [PATCH] [AltStoreCore] Adds StoreApp.category + StoreCategory enum --- AltStore.xcodeproj/project.pbxproj | 4 ++ .../AltStore 14.xcdatamodel/contents | 1 + AltStoreCore/Model/StoreApp.swift | 18 +++++- AltStoreCore/Types/StoreCategory.swift | 64 +++++++++++++++++++ 4 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 AltStoreCore/Types/StoreCategory.swift diff --git a/AltStore.xcodeproj/project.pbxproj b/AltStore.xcodeproj/project.pbxproj index 791e2c9f..60a855ed 100644 --- a/AltStore.xcodeproj/project.pbxproj +++ b/AltStore.xcodeproj/project.pbxproj @@ -358,6 +358,7 @@ D52A2F972ACB40F700BDF8E3 /* Logger+AltStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52A2F962ACB40F700BDF8E3 /* Logger+AltStore.swift */; }; D52B4ABF2AF183F0005991C3 /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52B4ABE2AF183F0005991C3 /* WebViewController.swift */; }; D52C08EE28AEC37A006C4AE5 /* AppVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52C08ED28AEC37A006C4AE5 /* AppVersion.swift */; }; + D52C8F032AFC56F000CA0BDD /* StoreCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52C8F022AFC56F000CA0BDD /* StoreCategory.swift */; }; D52DD35E2AAA89A600A7F2B6 /* AltSign-Dynamic in Frameworks */ = {isa = PBXBuildFile; productRef = D52DD35D2AAA89A600A7F2B6 /* AltSign-Dynamic */; }; D52EF2BE2A0594550096C377 /* AppDetailCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52EF2BD2A0594550096C377 /* AppDetailCollectionViewController.swift */; }; D533E8B72727841800A9B5DD /* libAppleArchive.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D533E8B62727841800A9B5DD /* libAppleArchive.tbd */; settings = {ATTRIBUTES = (Weak, ); }; }; @@ -1037,6 +1038,7 @@ D52A2F962ACB40F700BDF8E3 /* Logger+AltStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Logger+AltStore.swift"; sourceTree = ""; }; D52B4ABE2AF183F0005991C3 /* WebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewController.swift; sourceTree = ""; }; D52C08ED28AEC37A006C4AE5 /* AppVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppVersion.swift; sourceTree = ""; }; + D52C8F022AFC56F000CA0BDD /* StoreCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreCategory.swift; sourceTree = ""; }; D52E988928D002D30032BE6B /* AltStore 11.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "AltStore 11.xcdatamodel"; sourceTree = ""; }; D52EF2BD2A0594550096C377 /* AppDetailCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDetailCollectionViewController.swift; sourceTree = ""; }; D533E8B62727841800A9B5DD /* libAppleArchive.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libAppleArchive.tbd; path = usr/lib/libAppleArchive.tbd; sourceTree = SDKROOT; }; @@ -1656,6 +1658,7 @@ BFB39B5B252BC10E00D1BE50 /* Managed.swift */, D5F48B4929CD0B67002B52A4 /* AsyncManaged.swift */, D5893F812A141E4900E767CD /* KnownSource.swift */, + D52C8F022AFC56F000CA0BDD /* StoreCategory.swift */, D5DB81632B0410BC003F5F8B /* AppSorting.swift */, BF66EE8E2501AEBC007EE018 /* ALTAppPermissions.h */, BF66EE912501AEBC007EE018 /* ALTAppPermissions.m */, @@ -3206,6 +3209,7 @@ D5927D6929DCE28700D6898E /* AltStore11ToAltStore12.xcmappingmodel in Sources */, BF66EED62501AECA007EE018 /* NewsItem.swift in Sources */, BF66EEA72501AEC5007EE018 /* Campaign.swift in Sources */, + D52C8F032AFC56F000CA0BDD /* StoreCategory.swift in Sources */, BF66EE992501AEBC007EE018 /* ALTSourceUserInfoKey.m in Sources */, D557A4812AE85BB0007D0DCF /* Pledge.swift in Sources */, D557A4852AE88227007D0DCF /* PledgeTier.swift in Sources */, diff --git a/AltStoreCore/Model/AltStore.xcdatamodeld/AltStore 14.xcdatamodel/contents b/AltStoreCore/Model/AltStore.xcdatamodeld/AltStore 14.xcdatamodel/contents index 0e2fb7df..51c245cf 100644 --- a/AltStoreCore/Model/AltStore.xcdatamodeld/AltStore 14.xcdatamodel/contents +++ b/AltStoreCore/Model/AltStore.xcdatamodeld/AltStore 14.xcdatamodel/contents @@ -239,6 +239,7 @@ + diff --git a/AltStoreCore/Model/StoreApp.swift b/AltStoreCore/Model/StoreApp.swift index 194ab8cf..2f1b7c88 100644 --- a/AltStoreCore/Model/StoreApp.swift +++ b/AltStoreCore/Model/StoreApp.swift @@ -115,6 +115,14 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable @NSManaged public private(set) var localizedDescription: String @NSManaged @objc(size) internal var _size: Int32 + @nonobjc public var category: StoreCategory? { + guard let _category else { return nil } + + let category = StoreCategory(rawValue: _category) + return category + } + @NSManaged @objc(category) public private(set) var _category: String? + @NSManaged public private(set) var iconURL: URL @NSManaged public private(set) var screenshotURLs: [URL] @@ -259,6 +267,7 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable case isBeta = "beta" case versions case patreon + case category // Legacy case version @@ -282,10 +291,10 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable self.bundleIdentifier = try container.decode(String.self, forKey: .bundleIdentifier) self.developerName = try container.decode(String.self, forKey: .developerName) self.localizedDescription = try container.decode(String.self, forKey: .localizedDescription) + self.iconURL = try container.decode(URL.self, forKey: .iconURL) self.subtitle = try container.decodeIfPresent(String.self, forKey: .subtitle) - - self.iconURL = try container.decode(URL.self, forKey: .iconURL) + self.isBeta = try container.decodeIfPresent(Bool.self, forKey: .isBeta) ?? false var downloadURL = try container.decodeIfPresent(URL.self, forKey: .downloadURL) let platformURLs = try container.decodeIfPresent(PlatformURLs.self.self, forKey: .platformURLs) @@ -329,7 +338,10 @@ public class StoreApp: NSManagedObject, Decodable, Fetchable self.tintColor = tintColor } - self.isBeta = try container.decodeIfPresent(Bool.self, forKey: .isBeta) ?? false + if let rawCategory = try container.decodeIfPresent(String.self, forKey: .category) + { + self._category = rawCategory.lowercased() // Store raw (lowercased) category value. + } let appScreenshots: [AppScreenshot] diff --git a/AltStoreCore/Types/StoreCategory.swift b/AltStoreCore/Types/StoreCategory.swift new file mode 100644 index 00000000..bdfa7c7a --- /dev/null +++ b/AltStoreCore/Types/StoreCategory.swift @@ -0,0 +1,64 @@ +// +// StoreCategory.swift +// AltStoreCore +// +// Created by Riley Testut on 11/8/23. +// Copyright © 2023 Riley Testut. All rights reserved. +// + +import Foundation +import UIKit + +public enum StoreCategory: String, CaseIterable +{ + case developer + case entertainment + case games + case lifestyle + case photoAndVideo = "photo" + case social + case utilities + case other + + public var localizedName: String { + switch self + { + case .developer: NSLocalizedString("Developer", comment: "") + case .entertainment: NSLocalizedString("Entertainment", comment: "") + case .games: NSLocalizedString("Games", comment: "") + case .lifestyle: NSLocalizedString("Lifestyle", comment: "") + case .photoAndVideo: NSLocalizedString("Photo & Video", comment: "") + case .social: NSLocalizedString("Social", comment: "") + case .utilities: NSLocalizedString("Utilities", comment: "") + case .other: NSLocalizedString("Other", comment: "") + } + } + + public var symbolName: String { + switch self + { + case .developer: "terminal" + case .entertainment: "popcorn" + case .games: "gamecontroller" + case .lifestyle: "tree" + case .photoAndVideo: "camera" + case .social: "hand.wave" + case .utilities: "paperclip" + case .other: "square.stack.3d.up" + } + } + + public var tintColor: UIColor { + switch self + { + case .developer: UIColor.systemPurple + case .entertainment: UIColor.systemPink + case .games: UIColor.systemGreen + case .lifestyle: UIColor.systemYellow + case .photoAndVideo: UIColor.systemGray + case .social: UIColor.systemRed + case .utilities: UIColor.systemBlue + case .other: UIColor.black + } + } +}