Compare commits

...

16 Commits

Author SHA1 Message Date
Joelle Stickney
fa170bcf98 Update README.md
Signed-off-by: Joelle Stickney <joellestickney+commit@gmail.com>
2023-01-13 10:39:12 -05:00
Joe Mattiello
7939d46949 Merge pull request #219 from SoY0ung/file_sharing
Reset Pairing File and checking minimuxer log in app
2023-01-12 20:35:06 -05:00
SoY0ung
4a670ec091 You can check minimuxer log in Error Log Page 2023-01-09 16:17:00 +08:00
SoY0ung
10e57e59c4 You can access SideStore document from File App 2023-01-09 15:19:18 +08:00
SoY0ung
b9ec43ef34 Add 'Reset Pairing File' 2023-01-09 15:15:31 +08:00
SoY0ung
42197cd375 Fix Advanced Setting display error 2023-01-09 14:13:31 +08:00
jawshoeadan
704852973b Merge pull request #214 from jawshoeadan/remove-hardcoded-me
Update AltBackup.ipa to remove any hardcoded stuff
2023-01-07 18:02:56 -08:00
Jawshoeadan
056b4200df Update AltBackup.ipa 2023-01-04 21:55:00 -08:00
Joe Mattiello
250a7d8627 Merge pull request #213 from SideStore/feature/JoeMFixes
Joe M fixes for 1.0
2023-01-04 12:58:56 -05:00
Joseph Mattello
1ba51e161e Add placeholder for minimux retries
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
2023-01-04 12:20:08 -05:00
Joseph Mattello
32e58af896 add workflow to attach builds to PR
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
2023-01-04 09:54:29 -05:00
Joseph Mattello
312fa6fe76 final classes marked as final
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
2023-01-04 09:52:12 -05:00
Joseph Mattello
afbe0837ba allow simulator to launch w/o pairing file
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
2023-01-04 09:32:04 -05:00
Joseph Mattello
36ad2a720f log functions inlineable
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
2023-01-04 09:31:51 -05:00
Joseph Mattello
901e3b14bb add final class to some classes
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
2023-01-04 09:31:41 -05:00
Joseph Mattello
588d209f7b refs #160 codable feed structs
Signed-off-by: Joseph Mattello <mail@joemattiello.com>
2023-01-04 09:31:28 -05:00
73 changed files with 393 additions and 93 deletions

View File

@@ -0,0 +1,22 @@
name: Add artifact links to pull request and related issues
on:
workflow_run:
workflows: [Pull Request SideStore build]
types: [completed]
jobs:
artifacts-url-comments:
name: add artifact links to pull request and related issues job
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: add artifact links to pull request and related issues step
uses: tonyhallett/artifacts-url-comments@v1.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
prefix: Builds for this Pull Request are available at
suffix: Have a nice day.
format: name
addTo: pull
# addTo: pullandissues

View File

@@ -71,7 +71,7 @@ extension AnalyticsManager
} }
} }
class AnalyticsManager final class AnalyticsManager
{ {
static let shared = AnalyticsManager() static let shared = AnalyticsManager()

View File

@@ -25,7 +25,7 @@ extension AppContentViewController
} }
} }
class AppContentViewController: UITableViewController final class AppContentViewController: UITableViewController
{ {
var app: StoreApp! var app: StoreApp!

View File

@@ -8,7 +8,7 @@
import UIKit import UIKit
class PermissionCollectionViewCell: UICollectionViewCell final class PermissionCollectionViewCell: UICollectionViewCell
{ {
@IBOutlet var button: UIButton! @IBOutlet var button: UIButton!
@IBOutlet var textLabel: UILabel! @IBOutlet var textLabel: UILabel!
@@ -29,7 +29,7 @@ class PermissionCollectionViewCell: UICollectionViewCell
} }
} }
class AppContentTableViewCell: UITableViewCell final class AppContentTableViewCell: UITableViewCell
{ {
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize
{ {

View File

@@ -13,7 +13,7 @@ import Roxas
import Nuke import Nuke
class AppViewController: UIViewController final class AppViewController: UIViewController
{ {
var app: StoreApp! var app: StoreApp!
@@ -352,7 +352,7 @@ class AppViewController: UIViewController
extension AppViewController extension AppViewController
{ {
class func makeAppViewController(app: StoreApp) -> AppViewController final class func makeAppViewController(app: StoreApp) -> AppViewController
{ {
let storyboard = UIStoryboard(name: "Main", bundle: nil) let storyboard = UIStoryboard(name: "Main", bundle: nil)

View File

@@ -10,7 +10,7 @@ import UIKit
import AltStoreCore import AltStoreCore
class PermissionPopoverViewController: UIViewController final class PermissionPopoverViewController: UIViewController
{ {
var permission: AppPermission! var permission: AppPermission!

View File

@@ -11,7 +11,7 @@ import UIKit
import AltStoreCore import AltStoreCore
import Roxas import Roxas
class AppIDsViewController: UICollectionViewController final class AppIDsViewController: UICollectionViewController
{ {
private lazy var dataSource = self.makeDataSource() private lazy var dataSource = self.makeDataSource()

View File

@@ -30,7 +30,7 @@ extension AppDelegate
} }
@UIApplicationMain @UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate { final class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? var window: UIWindow?

View File

@@ -10,7 +10,7 @@ import UIKit
import AltSign import AltSign
class AuthenticationViewController: UIViewController final class AuthenticationViewController: UIViewController
{ {
var authenticationHandler: ((String, String, @escaping (Result<(ALTAccount, ALTAppleAPISession), Error>) -> Void) -> Void)? var authenticationHandler: ((String, String, @escaping (Result<(ALTAccount, ALTAppleAPISession), Error>) -> Void) -> Void)?
var completionHandler: (((ALTAccount, ALTAppleAPISession, String)?) -> Void)? var completionHandler: (((ALTAccount, ALTAppleAPISession, String)?) -> Void)?

View File

@@ -8,7 +8,7 @@
import UIKit import UIKit
class InstructionsViewController: UIViewController final class InstructionsViewController: UIViewController
{ {
var completionHandler: (() -> Void)? var completionHandler: (() -> Void)?

View File

@@ -12,7 +12,7 @@ import AltStoreCore
import AltSign import AltSign
import Roxas import Roxas
class RefreshAltStoreViewController: UIViewController final class RefreshAltStoreViewController: UIViewController
{ {
var context: AuthenticatedOperationContext! var context: AuthenticatedOperationContext!

View File

@@ -14,7 +14,7 @@ import IntentsUI
import AltSign import AltSign
class SelectTeamViewController: UITableViewController final class SelectTeamViewController: UITableViewController
{ {
public var teams: [ALTTeam]? public var teams: [ALTTeam]?
public var completionHandler: ((Result<ALTTeam, Swift.Error>) -> Void)? public var completionHandler: ((Result<ALTTeam, Swift.Error>) -> Void)?

View File

@@ -12,7 +12,7 @@ import Roxas
import Nuke import Nuke
@objc class BrowseCollectionViewCell: UICollectionViewCell @objc final class BrowseCollectionViewCell: UICollectionViewCell
{ {
var imageURLs: [URL] = [] { var imageURLs: [URL] = [] {
didSet { didSet {

View File

@@ -8,7 +8,7 @@
import UIKit import UIKit
class AppIconImageView: UIImageView final class AppIconImageView: UIImageView
{ {
override func awakeFromNib() override func awakeFromNib()
{ {

View File

@@ -8,7 +8,7 @@
import AVFoundation import AVFoundation
class BackgroundTaskManager final class BackgroundTaskManager
{ {
static let shared = BackgroundTaskManager() static let shared = BackgroundTaskManager()

View File

@@ -8,7 +8,7 @@
import UIKit import UIKit
class BannerCollectionViewCell: UICollectionViewCell final class BannerCollectionViewCell: UICollectionViewCell
{ {
private(set) var errorBadge: UIView? private(set) var errorBadge: UIView?
@IBOutlet private(set) var bannerView: AppBannerView! @IBOutlet private(set) var bannerView: AppBannerView!

View File

@@ -8,7 +8,7 @@
import UIKit import UIKit
class Button: UIButton final class Button: UIButton
{ {
override var intrinsicContentSize: CGSize { override var intrinsicContentSize: CGSize {
var size = super.intrinsicContentSize var size = super.intrinsicContentSize

View File

@@ -8,7 +8,7 @@
import UIKit import UIKit
class CollapsingTextView: UITextView final class CollapsingTextView: UITextView
{ {
var isCollapsed = true { var isCollapsed = true {
didSet { didSet {

View File

@@ -8,7 +8,7 @@
import UIKit import UIKit
class ForwardingNavigationController: UINavigationController final class ForwardingNavigationController: UINavigationController
{ {
override var childForStatusBarStyle: UIViewController? { override var childForStatusBarStyle: UIViewController? {
return self.topViewController return self.topViewController

View File

@@ -10,7 +10,7 @@ import UIKit
import Roxas import Roxas
class NavigationBar: UINavigationBar final class NavigationBar: UINavigationBar
{ {
@IBInspectable var automaticallyAdjustsItemPositions: Bool = true @IBInspectable var automaticallyAdjustsItemPositions: Bool = true

View File

@@ -8,7 +8,7 @@
import UIKit import UIKit
class PillButton: UIButton final class PillButton: UIButton
{ {
override var accessibilityValue: String? { override var accessibilityValue: String? {
get { get {

View File

@@ -16,7 +16,7 @@ extension TimeInterval
static let longToastViewDuration = 8.0 static let longToastViewDuration = 8.0
} }
class ToastView: RSTToastView final class ToastView: RSTToastView
{ {
var preferredDuration: TimeInterval var preferredDuration: TimeInterval

View File

@@ -9,7 +9,7 @@
import Foundation import Foundation
import OSLog import OSLog
let customLog = OSLog(subsystem: "org.sidestore.sidestore", public let customLog = OSLog(subsystem: "org.sidestore.sidestore",
category: "ios") category: "ios")
@@ -18,6 +18,7 @@ public extension OSLog {
/// - Parameters: /// - Parameters:
/// - message: String or format string /// - message: String or format string
/// - args: optional args for format string /// - args: optional args for format string
@inlinable
static func error(_ message: StaticString, _ args: CVarArg...) { static func error(_ message: StaticString, _ args: CVarArg...) {
os_log(message, log: customLog, type: .error, args) os_log(message, log: customLog, type: .error, args)
} }
@@ -26,6 +27,7 @@ public extension OSLog {
/// - Parameters: /// - Parameters:
/// - message: String or format string /// - message: String or format string
/// - args: optional args for format string /// - args: optional args for format string
@inlinable
static func info(_ message: StaticString, _ args: CVarArg...) { static func info(_ message: StaticString, _ args: CVarArg...) {
os_log(message, log: customLog, type: .info, args) os_log(message, log: customLog, type: .info, args)
} }
@@ -34,6 +36,7 @@ public extension OSLog {
/// - Parameters: /// - Parameters:
/// - message: String or format string /// - message: String or format string
/// - args: optional args for format string /// - args: optional args for format string
@inlinable
static func debug(_ message: StaticString, _ args: CVarArg...) { static func debug(_ message: StaticString, _ args: CVarArg...) {
os_log(message, log: customLog, type: .debug, args) os_log(message, log: customLog, type: .debug, args)
} }
@@ -45,6 +48,7 @@ public extension OSLog {
/// - Parameters: /// - Parameters:
/// - message: String or format string /// - message: String or format string
/// - args: optional args for format string /// - args: optional args for format string
@inlinable
public func ELOG(_ message: StaticString, file: StaticString = #file, function: StaticString = #function, line: UInt = #line, _ args: CVarArg...) { public func ELOG(_ message: StaticString, file: StaticString = #file, function: StaticString = #function, line: UInt = #line, _ args: CVarArg...) {
OSLog.error(message, args) OSLog.error(message, args)
} }
@@ -53,6 +57,7 @@ public func ELOG(_ message: StaticString, file: StaticString = #file, function:
/// - Parameters: /// - Parameters:
/// - message: String or format string /// - message: String or format string
/// - args: optional args for format string /// - args: optional args for format string
@inlinable
public func ILOG(_ message: StaticString, file: StaticString = #file, function: StaticString = #function, line: UInt = #line, _ args: CVarArg...) { public func ILOG(_ message: StaticString, file: StaticString = #file, function: StaticString = #function, line: UInt = #line, _ args: CVarArg...) {
OSLog.info(message, args) OSLog.info(message, args)
} }

View File

@@ -58,7 +58,7 @@
<key>CFBundleURLSchemes</key> <key>CFBundleURLSchemes</key>
<array> <array>
<string>altstore</string> <string>altstore</string>
<string>sidestore</string> <string>sidestore</string>
</array> </array>
</dict> </dict>
<dict> <dict>
@@ -69,7 +69,7 @@
<key>CFBundleURLSchemes</key> <key>CFBundleURLSchemes</key>
<array> <array>
<string>altstore-com.rileytestut.AltStore</string> <string>altstore-com.rileytestut.AltStore</string>
<string>sidestore-com.SideStore.SideStore</string> <string>sidestore-com.SideStore.SideStore</string>
</array> </array>
</dict> </dict>
</array> </array>
@@ -204,5 +204,7 @@
</dict> </dict>
</dict> </dict>
</array> </array>
<key>UIFileSharingEnabled</key>
<true/>
</dict> </dict>
</plist> </plist>

View File

@@ -11,7 +11,7 @@ import Foundation
import AltStoreCore import AltStoreCore
@available(iOS 14, *) @available(iOS 14, *)
class IntentHandler: NSObject, RefreshAllIntentHandling final class IntentHandler: NSObject, RefreshAllIntentHandling
{ {
private let queue = DispatchQueue(label: "io.altstore.IntentHandler") private let queue = DispatchQueue(label: "io.altstore.IntentHandler")

View File

@@ -14,7 +14,7 @@ import minimuxer
import AltStoreCore import AltStoreCore
import UniformTypeIdentifiers import UniformTypeIdentifiers
class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDelegate final class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDelegate
{ {
private var didFinishLaunching = false private var didFinishLaunching = false
@@ -47,6 +47,7 @@ class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDelegate
override func viewDidAppear(_ animated: Bool) { override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true) super.viewDidAppear(true)
#if !targetEnvironment(simulator)
start_em_proxy(bind_addr: Consts.Proxy.serverURL) start_em_proxy(bind_addr: Consts.Proxy.serverURL)
guard let pf = fetchPairingFile() else { guard let pf = fetchPairingFile() else {
@@ -54,6 +55,7 @@ class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDelegate
return return
} }
start_minimuxer_threads(pf) start_minimuxer_threads(pf)
#endif
} }
func fetchPairingFile() -> String? { func fetchPairingFile() -> String? {
@@ -147,7 +149,17 @@ class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDelegate
func start_minimuxer_threads(_ pairing_file: String) { func start_minimuxer_threads(_ pairing_file: String) {
set_usbmuxd_socket() set_usbmuxd_socket()
#if false // Retries
var res = start_minimuxer(pairing_file: pairing_file)
var attempts = 10
while (attempts != 0 && res != 0) {
print("start_minimuxer `res` != 0, retry #\(attempts)")
res = start_minimuxer(pairing_file: pairing_file)
attempts -= 1
}
#else
let res = start_minimuxer(pairing_file: pairing_file) let res = start_minimuxer(pairing_file: pairing_file)
#endif
if res != 0 { if res != 0 {
displayError("minimuxer failed to start. Incorrect arguments were passed.") displayError("minimuxer failed to start. Incorrect arguments were passed.")
} }

View File

@@ -28,7 +28,7 @@ extension AppManager
} }
@available(iOS 13, *) @available(iOS 13, *)
class AppManagerPublisher: ObservableObject final class AppManagerPublisher: ObservableObject
{ {
@Published @Published
fileprivate(set) var installationProgress = [String: Progress]() fileprivate(set) var installationProgress = [String: Progress]()
@@ -42,7 +42,7 @@ private func ==(lhs: OperatingSystemVersion, rhs: OperatingSystemVersion) -> Boo
return (lhs.majorVersion == rhs.majorVersion && lhs.minorVersion == rhs.minorVersion && lhs.patchVersion == rhs.patchVersion) return (lhs.majorVersion == rhs.majorVersion && lhs.minorVersion == rhs.minorVersion && lhs.patchVersion == rhs.patchVersion)
} }
class AppManager final class AppManager
{ {
static let shared = AppManager() static let shared = AppManager()
@@ -664,7 +664,7 @@ extension AppManager
@available(iOS 14, *) @available(iOS 14, *)
func enableJIT(for installedApp: InstalledApp, completionHandler: @escaping (Result<Void, Error>) -> Void) func enableJIT(for installedApp: InstalledApp, completionHandler: @escaping (Result<Void, Error>) -> Void)
{ {
class Context: OperationContext, EnableJITContext final class Context: OperationContext, EnableJITContext
{ {
var installedApp: InstalledApp? var installedApp: InstalledApp?
} }
@@ -684,7 +684,7 @@ extension AppManager
@available(iOS 14.0, *) @available(iOS 14.0, *)
func patch(resignedApp: ALTApplication, presentingViewController: UIViewController, context authContext: AuthenticatedOperationContext, completionHandler: @escaping (Result<InstalledApp, Error>) -> Void) -> PatchAppOperation func patch(resignedApp: ALTApplication, presentingViewController: UIViewController, context authContext: AuthenticatedOperationContext, completionHandler: @escaping (Result<InstalledApp, Error>) -> Void) -> PatchAppOperation
{ {
class Context: InstallAppOperationContext, PatchAppContext final class Context: InstallAppOperationContext, PatchAppContext
{ {
} }

View File

@@ -8,7 +8,7 @@
import UIKit import UIKit
class InstalledAppsCollectionHeaderView: UICollectionReusableView final class InstalledAppsCollectionHeaderView: UICollectionReusableView
{ {
let textLabel: UILabel let textLabel: UILabel
let button: UIButton let button: UIButton

View File

@@ -9,7 +9,7 @@
import UIKit import UIKit
import Roxas import Roxas
class InstalledAppCollectionViewCell: UICollectionViewCell final class InstalledAppCollectionViewCell: UICollectionViewCell
{ {
private(set) var deactivateBadge: UIView? private(set) var deactivateBadge: UIView?
@@ -55,13 +55,13 @@ class InstalledAppCollectionViewCell: UICollectionViewCell
} }
} }
class InstalledAppsCollectionFooterView: UICollectionReusableView final class InstalledAppsCollectionFooterView: UICollectionReusableView
{ {
@IBOutlet var textLabel: UILabel! @IBOutlet var textLabel: UILabel!
@IBOutlet var button: UIButton! @IBOutlet var button: UIButton!
} }
class NoUpdatesCollectionViewCell: UICollectionViewCell final class NoUpdatesCollectionViewCell: UICollectionViewCell
{ {
@IBOutlet var blurView: UIVisualEffectView! @IBOutlet var blurView: UIVisualEffectView!
@@ -73,7 +73,7 @@ class NoUpdatesCollectionViewCell: UICollectionViewCell
} }
} }
class UpdatesCollectionHeaderView: UICollectionReusableView final class UpdatesCollectionHeaderView: UICollectionReusableView
{ {
let button = PillButton(type: .system) let button = PillButton(type: .system)

View File

@@ -30,7 +30,7 @@ extension MyAppsViewController
} }
} }
class MyAppsViewController: UICollectionViewController final class MyAppsViewController: UICollectionViewController
{ {
private let coordinator = NSFileCoordinator() private let coordinator = NSFileCoordinator()
private let operationQueue = OperationQueue() private let operationQueue = OperationQueue()

View File

@@ -17,7 +17,7 @@ extension UpdateCollectionViewCell
} }
} }
@objc class UpdateCollectionViewCell: UICollectionViewCell @objc final class UpdateCollectionViewCell: UICollectionViewCell
{ {
var mode: Mode = .expanded { var mode: Mode = .expanded {
didSet { didSet {

View File

@@ -8,7 +8,7 @@
import UIKit import UIKit
class NewsCollectionViewCell: UICollectionViewCell final class NewsCollectionViewCell: UICollectionViewCell
{ {
@IBOutlet var titleLabel: UILabel! @IBOutlet var titleLabel: UILabel!
@IBOutlet var captionLabel: UILabel! @IBOutlet var captionLabel: UILabel!

View File

@@ -14,7 +14,7 @@ import Roxas
import Nuke import Nuke
private class AppBannerFooterView: UICollectionReusableView private final class AppBannerFooterView: UICollectionReusableView
{ {
let bannerView = AppBannerView(frame: .zero) let bannerView = AppBannerView(frame: .zero)
let tapGestureRecognizer = UITapGestureRecognizer(target: nil, action: nil) let tapGestureRecognizer = UITapGestureRecognizer(target: nil, action: nil)
@@ -41,7 +41,7 @@ private class AppBannerFooterView: UICollectionReusableView
} }
} }
class NewsViewController: UICollectionViewController final class NewsViewController: UICollectionViewController
{ {
private lazy var dataSource = self.makeDataSource() private lazy var dataSource = self.makeDataSource()
private lazy var placeholderView = RSTPlaceholderView(frame: .zero) private lazy var placeholderView = RSTPlaceholderView(frame: .zero)

View File

@@ -34,7 +34,7 @@ enum AuthenticationError: LocalizedError
} }
@objc(AuthenticationOperation) @objc(AuthenticationOperation)
class AuthenticationOperation: ResultOperation<(ALTTeam, ALTCertificate, ALTAppleAPISession)> final class AuthenticationOperation: ResultOperation<(ALTTeam, ALTCertificate, ALTAppleAPISession)>
{ {
let context: AuthenticatedOperationContext let context: AuthenticatedOperationContext

View File

@@ -51,7 +51,7 @@ private let ReceivedApplicationState: @convention(c) (CFNotificationCenter?, Uns
} }
@objc(BackgroundRefreshAppsOperation) @objc(BackgroundRefreshAppsOperation)
class BackgroundRefreshAppsOperation: ResultOperation<[String: Result<InstalledApp, Error>]> final class BackgroundRefreshAppsOperation: ResultOperation<[String: Result<InstalledApp, Error>]>
{ {
let installedApps: [InstalledApp] let installedApps: [InstalledApp]
private let managedObjectContext: NSManagedObjectContext private let managedObjectContext: NSManagedObjectContext

View File

@@ -14,7 +14,7 @@ import Roxas
import minimuxer import minimuxer
@objc(DeactivateAppOperation) @objc(DeactivateAppOperation)
class DeactivateAppOperation: ResultOperation<InstalledApp> final class DeactivateAppOperation: ResultOperation<InstalledApp>
{ {
let app: InstalledApp let app: InstalledApp
let context: OperationContext let context: OperationContext

View File

@@ -30,7 +30,7 @@ private extension DownloadAppOperation
} }
@objc(DownloadAppOperation) @objc(DownloadAppOperation)
class DownloadAppOperation: ResultOperation<ALTApplication> final class DownloadAppOperation: ResultOperation<ALTApplication>
{ {
let app: AppProtocol let app: AppProtocol
let context: AppOperationContext let context: AppOperationContext

View File

@@ -21,7 +21,7 @@ protocol EnableJITContext
} }
@available(iOS 14, *) @available(iOS 14, *)
class EnableJITOperation<Context: EnableJITContext>: ResultOperation<Void> final class EnableJITOperation<Context: EnableJITContext>: ResultOperation<Void>
{ {
let context: Context let context: Context

View File

@@ -13,7 +13,7 @@ import AltSign
import Roxas import Roxas
@objc(FetchAnisetteDataOperation) @objc(FetchAnisetteDataOperation)
class FetchAnisetteDataOperation: ResultOperation<ALTAnisetteData> final class FetchAnisetteDataOperation: ResultOperation<ALTAnisetteData>
{ {
let context: OperationContext let context: OperationContext

View File

@@ -13,7 +13,7 @@ import AltSign
import Roxas import Roxas
@objc(FetchAppIDsOperation) @objc(FetchAppIDsOperation)
class FetchAppIDsOperation: ResultOperation<([AppID], NSManagedObjectContext)> final class FetchAppIDsOperation: ResultOperation<([AppID], NSManagedObjectContext)>
{ {
let context: AuthenticatedOperationContext let context: AuthenticatedOperationContext
let managedObjectContext: NSManagedObjectContext let managedObjectContext: NSManagedObjectContext

View File

@@ -13,7 +13,7 @@ import AltSign
import Roxas import Roxas
@objc(FetchProvisioningProfilesOperation) @objc(FetchProvisioningProfilesOperation)
class FetchProvisioningProfilesOperation: ResultOperation<[String: ALTProvisioningProfile]> final class FetchProvisioningProfilesOperation: ResultOperation<[String: ALTProvisioningProfile]>
{ {
let context: AppOperationContext let context: AppOperationContext

View File

@@ -13,7 +13,7 @@ import AltStoreCore
import Roxas import Roxas
@objc(FetchSourceOperation) @objc(FetchSourceOperation)
class FetchSourceOperation: ResultOperation<Source> final class FetchSourceOperation: ResultOperation<Source>
{ {
let sourceURL: URL let sourceURL: URL
let managedObjectContext: NSManagedObjectContext let managedObjectContext: NSManagedObjectContext

View File

@@ -32,7 +32,7 @@ extension FetchTrustedSourcesOperation
} }
} }
class FetchTrustedSourcesOperation: ResultOperation<[FetchTrustedSourcesOperation.TrustedSource]> final class FetchTrustedSourcesOperation: ResultOperation<[FetchTrustedSourcesOperation.TrustedSource]>
{ {
override func main() override func main()
{ {

View File

@@ -13,7 +13,7 @@ import AltSign
import Roxas import Roxas
@objc(InstallAppOperation) @objc(InstallAppOperation)
class InstallAppOperation: ResultOperation<InstalledApp> final class InstallAppOperation: ResultOperation<InstalledApp>
{ {
let context: InstallAppOperationContext let context: InstallAppOperationContext

View File

@@ -38,7 +38,7 @@ class OperationContext
} }
} }
class AuthenticatedOperationContext: OperationContext final class AuthenticatedOperationContext: OperationContext
{ {
var session: ALTAppleAPISession? var session: ALTAppleAPISession?

View File

@@ -52,7 +52,7 @@ private struct OTAUpdate
} }
@available(iOS 14, *) @available(iOS 14, *)
class PatchAppOperation: ResultOperation<Void> final class PatchAppOperation: ResultOperation<Void>
{ {
let context: PatchAppContext let context: PatchAppContext

View File

@@ -29,7 +29,7 @@ extension PatchViewController
} }
@available(iOS 14.0, *) @available(iOS 14.0, *)
class PatchViewController: UIViewController final class PatchViewController: UIViewController
{ {
var patchApp: AnyApp? var patchApp: AnyApp?
var installedApp: InstalledApp? var installedApp: InstalledApp?

View File

@@ -14,7 +14,7 @@ import Roxas
import minimuxer import minimuxer
@objc(RefreshAppOperation) @objc(RefreshAppOperation)
class RefreshAppOperation: ResultOperation<InstalledApp> final class RefreshAppOperation: ResultOperation<InstalledApp>
{ {
let context: AppOperationContext let context: AppOperationContext

View File

@@ -12,7 +12,7 @@ import CoreData
import AltStoreCore import AltStoreCore
import AltSign import AltSign
class RefreshGroup: NSObject final class RefreshGroup: NSObject
{ {
let context: AuthenticatedOperationContext let context: AuthenticatedOperationContext
let progress = Progress.discreteProgress(totalUnitCount: 0) let progress = Progress.discreteProgress(totalUnitCount: 0)

View File

@@ -9,7 +9,7 @@
import Foundation import Foundation
@objc(RemoveAppBackupOperation) @objc(RemoveAppBackupOperation)
class RemoveAppBackupOperation: ResultOperation<Void> final class RemoveAppBackupOperation: ResultOperation<Void>
{ {
let context: InstallAppOperationContext let context: InstallAppOperationContext

View File

@@ -12,7 +12,7 @@ import AltStoreCore
import minimuxer import minimuxer
@objc(RemoveAppOperation) @objc(RemoveAppOperation)
class RemoveAppOperation: ResultOperation<InstalledApp> final class RemoveAppOperation: ResultOperation<InstalledApp>
{ {
let context: InstallAppOperationContext let context: InstallAppOperationContext

View File

@@ -13,7 +13,7 @@ import AltStoreCore
import AltSign import AltSign
@objc(ResignAppOperation) @objc(ResignAppOperation)
class ResignAppOperation: ResultOperation<ALTApplication> final class ResignAppOperation: ResultOperation<ALTApplication>
{ {
let context: InstallAppOperationContext let context: InstallAppOperationContext

View File

@@ -11,7 +11,7 @@ import Network
import AltStoreCore import AltStoreCore
@objc(SendAppOperation) @objc(SendAppOperation)
class SendAppOperation: ResultOperation<()> final class SendAppOperation: ResultOperation<()>
{ {
let context: InstallAppOperationContext let context: InstallAppOperationContext

View File

@@ -30,7 +30,7 @@ extension UpdatePatronsOperation
} }
} }
class UpdatePatronsOperation: ResultOperation<Void> final class UpdatePatronsOperation: ResultOperation<Void>
{ {
let context: NSManagedObjectContext let context: NSManagedObjectContext

View File

@@ -55,7 +55,7 @@ enum VerificationError: ALTLocalizedError
} }
@objc(VerifyAppOperation) @objc(VerifyAppOperation)
class VerifyAppOperation: ResultOperation<Void> final class VerifyAppOperation: ResultOperation<Void>
{ {
let context: AppOperationContext let context: AppOperationContext
var verificationHandler: ((VerificationError) -> Bool)? var verificationHandler: ((VerificationError) -> Bool)?

Binary file not shown.

View File

@@ -11,7 +11,7 @@ import AltStoreCore
import EmotionalDamage import EmotionalDamage
@available(iOS 13, *) @available(iOS 13, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate final class SceneDelegate: UIResponder, UIWindowSceneDelegate
{ {
var window: UIWindow? var window: UIWindow?

View File

@@ -9,7 +9,7 @@
import UIKit import UIKit
@objc(ErrorLogTableViewCell) @objc(ErrorLogTableViewCell)
class ErrorLogTableViewCell: UITableViewCell final class ErrorLogTableViewCell: UITableViewCell
{ {
@IBOutlet var appIconImageView: AppIconImageView! @IBOutlet var appIconImageView: AppIconImageView!

View File

@@ -14,7 +14,9 @@ import Roxas
import Nuke import Nuke
class ErrorLogViewController: UITableViewController import QuickLook
final class ErrorLogViewController: UITableViewController
{ {
private lazy var dataSource = self.makeDataSource() private lazy var dataSource = self.makeDataSource()
private var expandedErrorIDs = Set<NSManagedObjectID>() private var expandedErrorIDs = Set<NSManagedObjectID>()
@@ -176,6 +178,15 @@ private extension ErrorLogViewController
} }
} }
@IBAction func showMinimuxerLogs(_ sender: UIBarButtonItem)
{
// Show minimuxer.log
let previewController = QLPreviewController()
previewController.dataSource = self
let navigationController = UINavigationController(rootViewController: previewController)
present(navigationController, animated: true, completion: nil)
}
@IBAction func clearLoggedErrors(_ sender: UIBarButtonItem) @IBAction func clearLoggedErrors(_ sender: UIBarButtonItem)
{ {
let alertController = UIAlertController(title: NSLocalizedString("Are you sure you want to clear the error log?", comment: ""), message: nil, preferredStyle: .actionSheet) let alertController = UIAlertController(title: NSLocalizedString("Are you sure you want to clear the error log?", comment: ""), message: nil, preferredStyle: .actionSheet)
@@ -299,3 +310,14 @@ extension ErrorLogViewController
} }
} }
} }
extension ErrorLogViewController: QLPreviewControllerDataSource {
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
return 1
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
let fileURL = FileManager.default.documentsDirectory.appendingPathComponent("minimuxer.log")
return fileURL as QLPreviewItem
}
}

View File

@@ -19,7 +19,7 @@ extension InsetGroupTableViewCell
} }
} }
class InsetGroupTableViewCell: UITableViewCell final class InsetGroupTableViewCell: UITableViewCell
{ {
#if !TARGET_INTERFACE_BUILDER #if !TARGET_INTERFACE_BUILDER
@IBInspectable var style: Style = .single { @IBInspectable var style: Style = .single {

View File

@@ -8,7 +8,7 @@
import UIKit import UIKit
class LicensesViewController: UIViewController final class LicensesViewController: UIViewController
{ {
private var _didAppear = false private var _didAppear = false

View File

@@ -8,12 +8,12 @@
import UIKit import UIKit
class PatronCollectionViewCell: UICollectionViewCell final class PatronCollectionViewCell: UICollectionViewCell
{ {
@IBOutlet var textLabel: UILabel! @IBOutlet var textLabel: UILabel!
} }
class PatronsHeaderView: UICollectionReusableView final class PatronsHeaderView: UICollectionReusableView
{ {
let textLabel = UILabel() let textLabel = UILabel()
@@ -31,7 +31,7 @@ class PatronsHeaderView: UICollectionReusableView
} }
} }
class PatronsFooterView: UICollectionReusableView final class PatronsFooterView: UICollectionReusableView
{ {
let button = UIButton(type: .system) let button = UIButton(type: .system)
@@ -53,7 +53,7 @@ class PatronsFooterView: UICollectionReusableView
} }
} }
class AboutPatreonHeaderView: UICollectionReusableView final class AboutPatreonHeaderView: UICollectionReusableView
{ {
@IBOutlet var supportButton: UIButton! @IBOutlet var supportButton: UIButton!
@IBOutlet var accountButton: UIButton! @IBOutlet var accountButton: UIButton!

View File

@@ -22,7 +22,7 @@ extension PatreonViewController
} }
} }
class PatreonViewController: UICollectionViewController final class PatreonViewController: UICollectionViewController
{ {
private lazy var dataSource = self.makeDataSource() private lazy var dataSource = self.makeDataSource()
private lazy var patronsDataSource = self.makePatronsDataSource() private lazy var patronsDataSource = self.makePatronsDataSource()

View File

@@ -12,14 +12,14 @@ import AltStoreCore
import Roxas import Roxas
@objc(RefreshAttemptTableViewCell) @objc(RefreshAttemptTableViewCell)
private class RefreshAttemptTableViewCell: UITableViewCell private final class RefreshAttemptTableViewCell: UITableViewCell
{ {
@IBOutlet var successLabel: UILabel! @IBOutlet var successLabel: UILabel!
@IBOutlet var dateLabel: UILabel! @IBOutlet var dateLabel: UILabel!
@IBOutlet var errorDescriptionLabel: UILabel! @IBOutlet var errorDescriptionLabel: UILabel!
} }
class RefreshAttemptsViewController: UITableViewController final class RefreshAttemptsViewController: UITableViewController
{ {
private lazy var dataSource = self.makeDataSource() private lazy var dataSource = self.makeDataSource()

View File

@@ -21,7 +21,7 @@
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="separatorColor" white="1" alpha="0.25" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="separatorColor" white="1" alpha="0.25" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<label key="tableFooterView" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SideStore 1.0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="bUR-rp-Nw2"> <label key="tableFooterView" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SideStore 1.0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="bUR-rp-Nw2">
<rect key="frame" x="0.0" y="1092" width="375" height="25"/> <rect key="frame" x="0.0" y="1082" width="375" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="0.69999999999999996" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="0.69999999999999996" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -577,7 +577,7 @@
<edgeInsets key="layoutMargins" top="8" left="30" bottom="8" right="30"/> <edgeInsets key="layoutMargins" top="8" left="30" bottom="8" right="30"/>
<userDefinedRuntimeAttributes> <userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="style"> <userDefinedRuntimeAttribute type="number" keyPath="style">
<integer key="value" value="3"/> <integer key="value" value="2"/>
</userDefinedRuntimeAttribute> </userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="YES"/> <userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="YES"/>
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
@@ -585,9 +585,42 @@
<segue destination="g8a-Rf-zWa" kind="show" identifier="showErrorLog" id="SSW-vL-86I"/> <segue destination="g8a-Rf-zWa" kind="show" identifier="showErrorLog" id="SSW-vL-86I"/>
</connections> </connections>
</tableViewCell> </tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="fj2-EJ-Z98" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="VNn-u4-cN8" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="1023" width="375" height="51"/> <rect key="frame" x="0.0" y="1023" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="VNn-u4-cN8" id="4bh-qe-l2N">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Reset Pairing File" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ysS-9s-dXm">
<rect key="frame" x="30" y="15.5" width="140" height="20.5"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Next" translatesAutoresizingMaskIntoConstraints="NO" id="r09-mH-pOD">
<rect key="frame" x="327" y="16.5" width="18" height="18"/>
</imageView>
</subviews>
<constraints>
<constraint firstItem="r09-mH-pOD" firstAttribute="centerY" secondItem="4bh-qe-l2N" secondAttribute="centerY" id="02u-Os-L7r"/>
<constraint firstItem="ysS-9s-dXm" firstAttribute="centerY" secondItem="4bh-qe-l2N" secondAttribute="centerY" id="QOA-3E-85e"/>
<constraint firstItem="ysS-9s-dXm" firstAttribute="leading" secondItem="4bh-qe-l2N" secondAttribute="leadingMargin" id="gRE-CM-w21"/>
<constraint firstAttribute="trailingMargin" secondItem="r09-mH-pOD" secondAttribute="trailing" id="udf-VS-o6t"/>
</constraints>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="0.14999999999999999" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<edgeInsets key="layoutMargins" top="8" left="30" bottom="8" right="30"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="style">
<integer key="value" value="2"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="boolean" keyPath="isSelectable" value="YES"/>
</userDefinedRuntimeAttributes>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="51" id="fj2-EJ-Z98" customClass="InsetGroupTableViewCell" customModule="SideStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="1074" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="fj2-EJ-Z98" id="BcT-Fs-KNg"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="fj2-EJ-Z98" id="BcT-Fs-KNg">
<rect key="frame" x="0.0" y="0.0" width="375" height="51"/> <rect key="frame" x="0.0" y="0.0" width="375" height="51"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
@@ -1018,11 +1051,18 @@ Settings by i cons from the Noun Project</string>
</connections> </connections>
</tableView> </tableView>
<navigationItem key="navigationItem" title="Error Log" largeTitleDisplayMode="never" id="a1p-3W-bSi"> <navigationItem key="navigationItem" title="Error Log" largeTitleDisplayMode="never" id="a1p-3W-bSi">
<barButtonItem key="rightBarButtonItem" systemItem="trash" id="BnQ-Eh-1gC"> <rightBarButtonItems>
<connections> <barButtonItem systemItem="trash" id="BnQ-Eh-1gC">
<action selector="clearLoggedErrors:" destination="g8a-Rf-zWa" id="faq-89-H5j"/> <connections>
</connections> <action selector="clearLoggedErrors:" destination="g8a-Rf-zWa" id="faq-89-H5j"/>
</barButtonItem> </connections>
</barButtonItem>
<barButtonItem image="ladybug" catalog="system" id="1cD-4y-vTJ" userLabel="Share">
<connections>
<action selector="showMinimuxerLogs:" destination="g8a-Rf-zWa" id="V0f-0y-C6C"/>
</connections>
</barButtonItem>
</rightBarButtonItems>
</navigationItem> </navigationItem>
</tableViewController> </tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="rU1-TZ-TD8" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="rU1-TZ-TD8" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -1033,6 +1073,7 @@ Settings by i cons from the Noun Project</string>
<resources> <resources>
<image name="Next" width="18" height="18"/> <image name="Next" width="18" height="18"/>
<image name="Settings" width="20" height="20"/> <image name="Settings" width="20" height="20"/>
<image name="ladybug" catalog="system" width="128" height="122"/>
<namedColor name="SettingsBackground"> <namedColor name="SettingsBackground">
<color red="0.45098039215686275" green="0.015686274509803921" blue="0.68627450980392157" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.45098039215686275" green="0.015686274509803921" blue="0.68627450980392157" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor> </namedColor>

View File

@@ -10,7 +10,7 @@ import UIKit
import Roxas import Roxas
class SettingsHeaderFooterView: UITableViewHeaderFooterView final class SettingsHeaderFooterView: UITableViewHeaderFooterView
{ {
@IBOutlet var primaryLabel: UILabel! @IBOutlet var primaryLabel: UILabel!
@IBOutlet var secondaryLabel: UILabel! @IBOutlet var secondaryLabel: UILabel!

View File

@@ -53,11 +53,12 @@ extension SettingsViewController
case sendFeedback case sendFeedback
case refreshAttempts case refreshAttempts
case errorLog case errorLog
case resetPairingFile
case advancedSettings case advancedSettings
} }
} }
class SettingsViewController: UITableViewController final class SettingsViewController: UITableViewController
{ {
private var activeTeam: Team? private var activeTeam: Team?
@@ -268,6 +269,8 @@ private extension SettingsViewController
let alertController = UIAlertController(title: NSLocalizedString("Are you sure you want to sign out?", comment: ""), message: NSLocalizedString("You will no longer be able to install or refresh apps once you sign out.", comment: ""), preferredStyle: .actionSheet) let alertController = UIAlertController(title: NSLocalizedString("Are you sure you want to sign out?", comment: ""), message: NSLocalizedString("You will no longer be able to install or refresh apps once you sign out.", comment: ""), preferredStyle: .actionSheet)
alertController.addAction(UIAlertAction(title: NSLocalizedString("Sign Out", comment: ""), style: .destructive) { _ in signOut() }) alertController.addAction(UIAlertAction(title: NSLocalizedString("Sign Out", comment: ""), style: .destructive) { _ in signOut() })
alertController.addAction(.cancel) alertController.addAction(.cancel)
//Fix crash on iPad
alertController.popoverPresentationController?.barButtonItem = sender
self.present(alertController, animated: true, completion: nil) self.present(alertController, animated: true, completion: nil)
} }
@@ -503,6 +506,30 @@ extension SettingsViewController
let toastView = ToastView(text: NSLocalizedString("Cannot Send Mail", comment: ""), detailText: nil) let toastView = ToastView(text: NSLocalizedString("Cannot Send Mail", comment: ""), detailText: nil)
toastView.show(in: self) toastView.show(in: self)
} }
case .resetPairingFile:
let filename = "ALTPairingFile.mobiledevicepairing"
let fm = FileManager.default
let documentsPath = fm.documentsDirectory.appendingPathComponent("/\(filename)")
let alertController = UIAlertController(
title: NSLocalizedString("Are you sure to reset the pairing file?", comment: ""),
message: NSLocalizedString("You can reset the pairing file when you cannot sideload apps or enable JIT. You need to restart SideStore.", comment: ""),
preferredStyle: UIAlertController.Style.actionSheet)
alertController.addAction(UIAlertAction(title: NSLocalizedString("Delete and Reset", comment: ""), style: .destructive){ _ in
if fm.fileExists(atPath: documentsPath.path), let contents = try? String(contentsOf: documentsPath), !contents.isEmpty {
try? fm.removeItem(atPath: documentsPath.path)
NSLog("Pairing File Reseted")
}
self.tableView.deselectRow(at: indexPath, animated: true)
let dialogMessage = UIAlertController(title: NSLocalizedString("Pairing File Reseted", comment: ""), message: NSLocalizedString("Please restart SideStore", comment: ""), preferredStyle: .alert)
self.present(dialogMessage, animated: true, completion: nil)
})
alertController.addAction(.cancel)
//Fix crash on iPad
alertController.popoverPresentationController?.sourceView = self.tableView
alertController.popoverPresentationController?.sourceRect = self.tableView.rectForRow(at: indexPath)
self.present(alertController, animated: true)
self.tableView.deselectRow(at: indexPath, animated: true)
case .advancedSettings: case .advancedSettings:
// Create the URL that deep links to your app's custom settings. // Create the URL that deep links to your app's custom settings.
if let url = URL(string: UIApplication.openSettingsURLString) { if let url = URL(string: UIApplication.openSettingsURLString) {

View File

@@ -31,7 +31,7 @@ struct SourceError: LocalizedError
} }
@objc(SourcesFooterView) @objc(SourcesFooterView)
private class SourcesFooterView: TextCollectionReusableView private final class SourcesFooterView: TextCollectionReusableView
{ {
@IBOutlet var activityIndicatorView: UIActivityIndicatorView! @IBOutlet var activityIndicatorView: UIActivityIndicatorView!
@IBOutlet var textView: UITextView! @IBOutlet var textView: UITextView!
@@ -46,7 +46,7 @@ extension SourcesViewController
} }
} }
class SourcesViewController: UICollectionViewController final class SourcesViewController: UICollectionViewController
{ {
var deepLinkSourceURL: URL? { var deepLinkSourceURL: URL? {
didSet { didSet {

View File

@@ -20,7 +20,7 @@ extension TabBarController
} }
} }
class TabBarController: UITabBarController final class TabBarController: UITabBarController
{ {
private var initialSegue: (identifier: String, sender: Any?)? private var initialSegue: (identifier: String, sender: Any?)?

View File

@@ -7,6 +7,7 @@
// //
import CoreData import CoreData
import UIKit
public extension Source public extension Source
{ {
@@ -35,6 +36,146 @@ public extension Source
#endif #endif
} }
public struct AppPermissionFeed: Codable {
let type: String // ALTAppPermissionType
let usageDescription: String
enum CodingKeys: String, CodingKey
{
case type
case usageDescription
}
}
public struct AppVersionFeed: Codable {
/* Properties */
let version: String
let date: Date
let localizedDescription: String?
let downloadURL: URL
let size: Int64
enum CodingKeys: String, CodingKey
{
case version
case date
case localizedDescription
case downloadURL
case size
}
}
public struct PlatformURLFeed: Codable {
/* Properties */
let platform: Platform
let downloadURL: URL
private enum CodingKeys: String, CodingKey
{
case platform
case downloadURL
}
}
public struct StoreAppFeed: Codable {
let name: String
let bundleIdentifier: String
let subtitle: String?
let developerName: String
let localizedDescription: String
let size: Int64
let iconURL: URL
let screenshotURLs: [URL]
let version: String
let versionDate: Date
let versionDescription: String?
let downloadURL: URL
let platformURLs: [PlatformURLFeed]?
let tintColor: String? // UIColor?
let isBeta: Bool
// let source: Source?
let appPermission: [AppPermissionFeed]
let versions: [AppVersionFeed]
enum CodingKeys: String, CodingKey
{
case bundleIdentifier
case developerName
case downloadURL
case iconURL
case isBeta = "beta"
case localizedDescription
case name
case appPermission = "permissions"
case platformURLs
case screenshotURLs
case size
case subtitle
case tintColor
case version
case versionDate
case versionDescription
case versions
}
}
public struct NewsItemFeed: Codable {
let identifier: String
let date: Date
let title: String
let caption: String
let tintColor: String //UIColor
let notify: Bool
let imageURL: URL?
let externalURL: URL?
let appID: String?
private enum CodingKeys: String, CodingKey
{
case identifier
case date
case title
case caption
case tintColor
case imageURL
case externalURL = "url"
case appID
case notify
}
}
public struct SourceJSON: Codable {
let name: String
let identifier: String
let sourceURL: URL
let userInfo: [String:String]? //[ALTSourceUserInfoKey:String]?
let apps: [StoreAppFeed]
let news: [NewsItemFeed]
enum CodingKeys: String, CodingKey
{
case name
case identifier
case sourceURL
case userInfo
case apps
case news
}
}
@objc(Source) @objc(Source)
public class Source: NSManagedObject, Fetchable, Decodable public class Source: NSManagedObject, Fetchable, Decodable
{ {

View File

@@ -26,14 +26,12 @@ public extension StoreApp
} }
@objc @objc
public enum Platform: UInt { public enum Platform: UInt, Codable {
case ios case ios
case tvos case tvos
case macos case macos
} }
extension Platform: Decodable {}
@objc @objc
public final class PlatformURL: NSManagedObject, Decodable { public final class PlatformURL: NSManagedObject, Decodable {
/* Properties */ /* Properties */

View File

@@ -25,7 +25,7 @@ Why iOS 14? Targeting such a recent version of iOS allows us to accelerate devel
SideStore is a just regular, sandboxed iOS application. The AltStore app target contains the vast majority of SideStore's functionality, including all the logic for downloading and updating apps through SideStore. SideStore makes heavy use of standard iOS frameworks and technologies most iOS developers are familiar with. SideStore is a just regular, sandboxed iOS application. The AltStore app target contains the vast majority of SideStore's functionality, including all the logic for downloading and updating apps through SideStore. SideStore makes heavy use of standard iOS frameworks and technologies most iOS developers are familiar with.
### EM Proxy ### EM Proxy
[EM-Proxy](https://github.com/jkcoxson/em_proxy) powers the defining feature of SideStore: untethered app installation. By levaraging an App Store app with additional entitlements (WireGuard) to create the VPN tunnel for us, it allows SideStore to take advantage of [Jitterbug](https://github.com/osy/Jitterbug)'s loopback method without requiring a paid developer account. [SideServer mobile](https://github.com/jkcoxson/em_proxy) powers the defining feature of SideStore: untethered app installation. By levaraging an App Store app with additional entitlements (WireGuard) to create the VPN tunnel for us, it allows SideStore to take advantage of [Jitterbug](https://github.com/osy/Jitterbug)'s loopback method without requiring a paid developer account.
### Minimuxer ### Minimuxer
[Minimuxer](https://github.com/jkcoxson/minimuxer) is a lockdown muxer that can run inside iOSs sandbox. It replicates Apples usbmuxd protocol on MacOS to “discover” devices to interface with wireguard On-Device. [Minimuxer](https://github.com/jkcoxson/minimuxer) is a lockdown muxer that can run inside iOSs sandbox. It replicates Apples usbmuxd protocol on MacOS to “discover” devices to interface with wireguard On-Device.

View File

@@ -27,7 +27,17 @@ public func set_usbmuxd_socket() {
public func debug_app(app_id: String) throws -> Uhoh { public func debug_app(app_id: String) throws -> Uhoh {
let ai = NSString(string: app_id) let ai = NSString(string: app_id)
let ai_pointer = UnsafeMutablePointer<CChar>(mutating: ai.utf8String) let ai_pointer = UnsafeMutablePointer<CChar>(mutating: ai.utf8String)
#if false // Retries
var res = minimuxer_debug_app(ai_pointer)
var attempts = 10
while (attempts != 0 && res != 0) {
print("(JIT) ATTEMPTS: \(attempts)")
res = minimuxer_debug_app(ai_pointer)
attempts -= 1
}
#else
let res = minimuxer_debug_app(ai_pointer) let res = minimuxer_debug_app(ai_pointer)
#endif
if res != 0 { if res != 0 {
throw Uhoh.Bad(code: res) throw Uhoh.Bad(code: res)
} }
@@ -38,7 +48,17 @@ public func install_provisioning_profile(plist: Data) throws -> Uhoh {
let pls = String(decoding: plist, as: UTF8.self) let pls = String(decoding: plist, as: UTF8.self)
print(pls) print(pls)
print(plist) print(plist)
#if false // Retries
var res = minimuxer_install_provisioning_profile(x, UInt32(plist.count))
var attempts = 10
while (attempts != 0 && res != 0) {
print("(INSTALL) ATTEMPTS: \(attempts)")
res = minimuxer_install_provisioning_profile(x, UInt32(plist.count))
attempts -= 1
}
#else
let x = plist.withUnsafeBytes { buf in UnsafeMutableRawPointer(mutating: buf) } let x = plist.withUnsafeBytes { buf in UnsafeMutableRawPointer(mutating: buf) }
#endif
let res = minimuxer_install_provisioning_profile(x, UInt32(plist.count)) let res = minimuxer_install_provisioning_profile(x, UInt32(plist.count))
if res != 0 { if res != 0 {
throw Uhoh.Bad(code: res) throw Uhoh.Bad(code: res)
@@ -49,7 +69,17 @@ public func install_provisioning_profile(plist: Data) throws -> Uhoh {
public func remove_provisioning_profile(id: String) throws -> Uhoh { public func remove_provisioning_profile(id: String) throws -> Uhoh {
let id_ns = NSString(string: id) let id_ns = NSString(string: id)
let id_pointer = UnsafeMutablePointer<CChar>(mutating: id_ns.utf8String) let id_pointer = UnsafeMutablePointer<CChar>(mutating: id_ns.utf8String)
#if false // Retries
var res = minimuxer_remove_provisioning_profile(id_pointer)
var attempts = 10
while (attempts != 0 && res != 0) {
print("(REMOVE PROFILE) ATTEMPTS: \(attempts)")
res = minimuxer_remove_provisioning_profile(id_pointer)
attempts -= 1
}
#else
let res = minimuxer_remove_provisioning_profile(id_pointer) let res = minimuxer_remove_provisioning_profile(id_pointer)
#endif
if res != 0 { if res != 0 {
throw Uhoh.Bad(code: res) throw Uhoh.Bad(code: res)
} }