[ADD] Authentication view for connecting SideStore to an Apple ID

This commit is contained in:
Fabian Thies
2022-12-12 19:12:38 +01:00
parent 3e0379dc70
commit d1e6ddd435
6 changed files with 425 additions and 127 deletions

View File

@@ -18,10 +18,17 @@
1920B04F2924AC8300744F60 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 1920B04E2924AC8300744F60 /* Settings.bundle */; };
19B9B7452845E6DF0076EF69 /* SelectTeamViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B9B7442845E6DF0076EF69 /* SelectTeamViewController.swift */; };
1F0DD810293222DF007608A4 /* AsyncImage in Frameworks */ = {isa = PBXBuildFile; productRef = 1F0DD80F293222DF007608A4 /* AsyncImage */; };
1F0DD81329322487007608A4 /* LazyScrollingVStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0DD81229322487007608A4 /* LazyScrollingVStack.swift */; };
1F0DD81C2932D2FF007608A4 /* AppScreenshotsScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0DD81B2932D2FF007608A4 /* AppScreenshotsScrollView.swift */; };
1F0DD81F2932D84C007608A4 /* ExpandableText in Frameworks */ = {isa = PBXBuildFile; productRef = 1F0DD81E2932D84C007608A4 /* ExpandableText */; };
1F0DD8212933B749007608A4 /* AppPermissionsGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0DD8202933B749007608A4 /* AppPermissionsGrid.swift */; };
1F0DD83F29367F6C007608A4 /* ConnectAppleIDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0DD83E29367F6C007608A4 /* ConnectAppleIDView.swift */; };
1F0DD84129368056007608A4 /* EnvironmentValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0DD84029368056007608A4 /* EnvironmentValues.swift */; };
1F0DD8432936B0F9007608A4 /* RoundedTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0DD8422936B0F9007608A4 /* RoundedTextField.swift */; };
1F0DD8452936B3FE007608A4 /* FilledButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0DD8442936B3FE007608A4 /* FilledButtonStyle.swift */; };
1F66F5BA2938CA5700A910CA /* VisualEffectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F66F5B92938CA5700A910CA /* VisualEffectView.swift */; };
1F66F5BC2938F03700A910CA /* Modifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F66F5BB2938F03700A910CA /* Modifiers.swift */; };
1F66F5BE2938F06100A910CA /* StoreApp+Filterable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F66F5BD2938F06100A910CA /* StoreApp+Filterable.swift */; };
1F66F5C02938F07C00A910CA /* Filterable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F66F5BF2938F07C00A910CA /* Filterable.swift */; };
1F6E08DA292806E0005059C0 /* AppRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F6E08D9292806E0005059C0 /* AppRowView.swift */; };
1F6E08DC292807D3005059C0 /* AppIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F6E08DB292807D3005059C0 /* AppIconView.swift */; };
1F6E08E029280B12005059C0 /* SafariView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F6E08DF29280B12005059C0 /* SafariView.swift */; };
@@ -541,9 +548,16 @@
191E5FD1290A651D001A3B7C /* jsmn.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jsmn.h; path = Dependencies/libplist/src/jsmn.h; sourceTree = SOURCE_ROOT; };
1920B04E2924AC8300744F60 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
19B9B7442845E6DF0076EF69 /* SelectTeamViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectTeamViewController.swift; sourceTree = "<group>"; };
1F0DD81229322487007608A4 /* LazyScrollingVStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazyScrollingVStack.swift; sourceTree = "<group>"; };
1F0DD81B2932D2FF007608A4 /* AppScreenshotsScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppScreenshotsScrollView.swift; sourceTree = "<group>"; };
1F0DD8202933B749007608A4 /* AppPermissionsGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppPermissionsGrid.swift; sourceTree = "<group>"; };
1F0DD83E29367F6C007608A4 /* ConnectAppleIDView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectAppleIDView.swift; sourceTree = "<group>"; };
1F0DD84029368056007608A4 /* EnvironmentValues.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnvironmentValues.swift; sourceTree = "<group>"; };
1F0DD8422936B0F9007608A4 /* RoundedTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedTextField.swift; sourceTree = "<group>"; };
1F0DD8442936B3FE007608A4 /* FilledButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilledButtonStyle.swift; sourceTree = "<group>"; };
1F66F5B92938CA5700A910CA /* VisualEffectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisualEffectView.swift; sourceTree = "<group>"; };
1F66F5BB2938F03700A910CA /* Modifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modifiers.swift; sourceTree = "<group>"; };
1F66F5BD2938F06100A910CA /* StoreApp+Filterable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StoreApp+Filterable.swift"; sourceTree = "<group>"; };
1F66F5BF2938F07C00A910CA /* Filterable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filterable.swift; sourceTree = "<group>"; };
1F6E08D9292806E0005059C0 /* AppRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRowView.swift; sourceTree = "<group>"; };
1F6E08DB292807D3005059C0 /* AppIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIconView.swift; sourceTree = "<group>"; };
1F6E08DF29280B12005059C0 /* SafariView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariView.swift; sourceTree = "<group>"; };
@@ -1032,19 +1046,13 @@
path = "libimobiledevice-glue/src";
sourceTree = "<group>";
};
1F0DD81129322472007608A4 /* Layout */ = {
isa = PBXGroup;
children = (
1F0DD81229322487007608A4 /* LazyScrollingVStack.swift */,
);
path = Layout;
sourceTree = "<group>";
};
1F6E08DD29280AF1005059C0 /* View Extensions */ = {
isa = PBXGroup;
children = (
1FB96FF1292D051F007E68D1 /* Styles */,
1F6E08DE29280AFF005059C0 /* UIView Representables */,
1F0DD84029368056007608A4 /* EnvironmentValues.swift */,
1F66F5BB2938F03700A910CA /* Modifiers.swift */,
);
path = "View Extensions";
sourceTree = "<group>";
@@ -1054,6 +1062,7 @@
children = (
1F6E08DF29280B12005059C0 /* SafariView.swift */,
1FB96FCE292BBBC9007E68D1 /* SiriShortcutSetupView.swift */,
1F66F5B92938CA5700A910CA /* VisualEffectView.swift */,
);
path = "UIView Representables";
sourceTree = "<group>";
@@ -1131,6 +1140,7 @@
isa = PBXGroup;
children = (
1FAFC5C02927E13C00B8D837 /* SettingsView.swift */,
1F0DD83E29367F6C007608A4 /* ConnectAppleIDView.swift */,
);
path = Settings;
sourceTree = "<group>";
@@ -1140,6 +1150,7 @@
children = (
1FAFC5C32927E18100B8D837 /* NavigationTab.swift */,
1F943C672927F39400ABE095 /* ViewModel.swift */,
1F66F5BF2938F07C00A910CA /* Filterable.swift */,
);
path = Protocols;
sourceTree = "<group>";
@@ -1147,12 +1158,12 @@
1FB84BA72928E073006A5CF4 /* View Components */ = {
isa = PBXGroup;
children = (
1F0DD81129322472007608A4 /* Layout */,
1F6E08D9292806E0005059C0 /* AppRowView.swift */,
1F6E08DB292807D3005059C0 /* AppIconView.swift */,
1F6E08E529280F4B005059C0 /* RatingStars.swift */,
1FB96FBD292A20E5007E68D1 /* ObservableScrollView.swift */,
1FB96FBF292A63F2007E68D1 /* AppPillButton.swift */,
1F0DD8422936B0F9007608A4 /* RoundedTextField.swift */,
);
path = "View Components";
sourceTree = "<group>";
@@ -1178,6 +1189,7 @@
children = (
1F6E08E329280D1E005059C0 /* PillButtonStyle.swift */,
1FB96FF2292D0539007E68D1 /* PillButtonProgressViewStyle.swift */,
1F0DD8442936B3FE007608A4 /* FilledButtonStyle.swift */,
);
path = Styles;
sourceTree = "<group>";
@@ -1864,6 +1876,7 @@
BFE00A1F2503097F00EB4D0C /* INInteraction+AltStore.swift */,
D57F2C9326E01BC700B9FA39 /* UIDevice+Vibration.swift */,
B376FE3D29258C8900E18883 /* OSLog+SideStore.swift */,
1F66F5BD2938F06100A910CA /* StoreApp+Filterable.swift */,
);
path = Extensions;
sourceTree = "<group>";
@@ -2683,6 +2696,7 @@
1F943C6C2927F90400ABE095 /* SettingsView.swift in Sources */,
BFDB6A0D22AAFC1A007EA6D6 /* OperationError.swift in Sources */,
BF74989B23621C0700CED65F /* ForwardingNavigationController.swift in Sources */,
1F66F5C02938F07C00A910CA /* Filterable.swift in Sources */,
BF3D649D22E7AC1B00E9056B /* PermissionPopoverViewController.swift in Sources */,
D57F2C9426E01BC700B9FA39 /* UIDevice+Vibration.swift in Sources */,
BFD2478F2284C8F900981D42 /* Button.swift in Sources */,
@@ -2696,9 +2710,11 @@
1F6E08E829282174005059C0 /* ConfirmAddSourceView.swift in Sources */,
BFE6073A231ADF82002B0E8E /* SettingsViewController.swift in Sources */,
1F943C6A2927F8F700ABE095 /* ViewModel.swift in Sources */,
1F0DD8432936B0F9007608A4 /* RoundedTextField.swift in Sources */,
D57F2C9126E0070200B9FA39 /* EnableJITOperation.swift in Sources */,
BF8CAE4E248AEABA004D6CCE /* UIDevice+Jailbreak.swift in Sources */,
1FB96FC7292A853D007E68D1 /* SourcesView.swift in Sources */,
1F66F5BE2938F06100A910CA /* StoreApp+Filterable.swift in Sources */,
D5E1E7C128077DE90016FC96 /* FetchTrustedSourcesOperation.swift in Sources */,
BFE338DF22F0EADB002E24B9 /* FetchSourceOperation.swift in Sources */,
D54DED1428CBC44B008B27A0 /* ErrorLogTableViewCell.swift in Sources */,
@@ -2707,12 +2723,12 @@
1F943C712927F90400ABE095 /* MyAppsView.swift in Sources */,
BF3BEFC124086A1E00DE7D55 /* RefreshAppOperation.swift in Sources */,
BFE60740231AFD2A002B0E8E /* InsetGroupTableViewCell.swift in Sources */,
1F0DD81329322487007608A4 /* LazyScrollingVStack.swift in Sources */,
BF0DCA662433BDF500E3A595 /* AnalyticsManager.swift in Sources */,
BFCCB51A245E3401001853EA /* VerifyAppOperation.swift in Sources */,
BFF0B6982322CAB8007A79E1 /* InstructionsViewController.swift in Sources */,
BF9ABA4522DCFF43008935CF /* BrowseViewController.swift in Sources */,
BF770E5422BC044E002A40FE /* OperationContexts.swift in Sources */,
1F0DD84129368056007608A4 /* EnvironmentValues.swift in Sources */,
BFD2478C2284C4C300981D42 /* AppIconImageView.swift in Sources */,
BF8F69C422E662D300049BA1 /* AppViewController.swift in Sources */,
BFF0B68E23219520007A79E1 /* PatreonViewController.swift in Sources */,
@@ -2749,6 +2765,7 @@
D5F2F6A92720B7C20081CCF5 /* PatchViewController.swift in Sources */,
B39F16132918D7C5002E9404 /* Consts.swift in Sources */,
1F0DD8212933B749007608A4 /* AppPermissionsGrid.swift in Sources */,
1F0DD8452936B3FE007608A4 /* FilledButtonStyle.swift in Sources */,
BF8F69C222E659F700049BA1 /* AppContentViewController.swift in Sources */,
BF08858522DE7EC800DE9F1E /* UpdateCollectionViewCell.swift in Sources */,
BFB39B5C252BC10E00D1BE50 /* Managed.swift in Sources */,
@@ -2766,12 +2783,15 @@
D57FE84428C7DB7100216002 /* ErrorLogViewController.swift in Sources */,
1F6E08E429280D1E005059C0 /* PillButtonStyle.swift in Sources */,
BFBE0007250AD0E70080826E /* ViewAppIntentHandler.swift in Sources */,
1F0DD83F29367F6C007608A4 /* ConnectAppleIDView.swift in Sources */,
BFDB6A0822AAED73007EA6D6 /* ResignAppOperation.swift in Sources */,
D593F1942717749A006E82DE /* PatchAppOperation.swift in Sources */,
BF770E5122BB1CF6002A40FE /* InstallAppOperation.swift in Sources */,
BF9ABA4B22DD1380008935CF /* NavigationBar.swift in Sources */,
BF6C8FAC242935ED00125131 /* NSAttributedString+Markdown.m in Sources */,
BFF00D322501BDA100746320 /* BackgroundRefreshAppsOperation.swift in Sources */,
1F66F5BC2938F03700A910CA /* Modifiers.swift in Sources */,
1F66F5BA2938CA5700A910CA /* VisualEffectView.swift in Sources */,
BF0C4EBD22A1BD8B009A2DD7 /* AppManager.swift in Sources */,
BF2901312318F7A800D88A45 /* AppBannerView.swift in Sources */,
BFF00D342501BDCF00746320 /* IntentHandler.swift in Sources */,
@@ -3458,6 +3478,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = AltStore/AltStore.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
@@ -3492,6 +3513,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = AltStore/AltStore.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";

View File

@@ -7,6 +7,7 @@
//
import Foundation
import SwiftUI
import Roxas
import Network
@@ -38,18 +39,18 @@ final class AuthenticationOperation: ResultOperation<(ALTTeam, ALTCertificate, A
{
let context: AuthenticatedOperationContext
private weak var presentingViewController: UIViewController?
private lazy var navigationController: UINavigationController = {
let navigationController = self.storyboard.instantiateViewController(withIdentifier: "navigationController") as! UINavigationController
if #available(iOS 13.0, *)
{
navigationController.isModalInPresentation = true
}
return navigationController
}()
private lazy var storyboard = UIStoryboard(name: "Authentication", bundle: nil)
// private weak var presentingViewController: UIViewController?
//
// private lazy var navigationController: UINavigationController = {
// let navigationController = self.storyboard.instantiateViewController(withIdentifier: "navigationController") as! UINavigationController
// if #available(iOS 13.0, *)
// {
// navigationController.isModalInPresentation = true
// }
// return navigationController
// }()
//
// private lazy var storyboard = UIStoryboard(name: "Authentication", bundle: nil)
private var appleIDEmailAddress: String?
private var appleIDPassword: String?
@@ -62,7 +63,7 @@ final class AuthenticationOperation: ResultOperation<(ALTTeam, ALTCertificate, A
init(context: AuthenticatedOperationContext, presentingViewController: UIViewController?)
{
self.context = context
self.presentingViewController = presentingViewController
// self.presentingViewController = presentingViewController
super.init()
@@ -266,7 +267,8 @@ final class AuthenticationOperation: ResultOperation<(ALTTeam, ALTCertificate, A
super.finish(result)
DispatchQueue.main.async {
self.navigationController.dismiss(animated: true, completion: nil)
// self.navigationController.dismiss(animated: true, completion: nil)
self.dismiss()
}
}
}
@@ -276,7 +278,8 @@ final class AuthenticationOperation: ResultOperation<(ALTTeam, ALTCertificate, A
super.finish(result)
DispatchQueue.main.async {
self.navigationController.dismiss(animated: true, completion: nil)
// self.navigationController.dismiss(animated: true, completion: nil)
self.dismiss()
}
}
}
@@ -287,25 +290,30 @@ private extension AuthenticationOperation
{
func present(_ viewController: UIViewController) -> Bool
{
guard let presentingViewController = self.presentingViewController else { return false }
self.navigationController.view.tintColor = .white
if self.navigationController.viewControllers.isEmpty
{
guard presentingViewController.presentedViewController == nil else { return false }
self.navigationController.setViewControllers([viewController], animated: false)
presentingViewController.present(self.navigationController, animated: true, completion: nil)
}
else
{
viewController.navigationItem.leftBarButtonItem = nil
self.navigationController.pushViewController(viewController, animated: true)
}
UIApplication.shared.keyWindow?.rootViewController?.present(viewController, animated: true)
// guard let presentingViewController = self.presentingViewController else { return false }
//
// self.navigationController.view.tintColor = .white
//
// if self.navigationController.viewControllers.isEmpty
// {
// guard presentingViewController.presentedViewController == nil else { return false }
//
// self.navigationController.setViewControllers([viewController], animated: false)
// presentingViewController.present(self.navigationController, animated: true, completion: nil)
// }
// else
// {
// viewController.navigationItem.leftBarButtonItem = nil
// self.navigationController.pushViewController(viewController, animated: true)
// }
return true
}
func dismiss() {
UIApplication.shared.keyWindow?.rootViewController?.presentedViewController?.dismiss(animated: true)
}
}
private extension AuthenticationOperation
@@ -315,29 +323,29 @@ private extension AuthenticationOperation
func authenticate()
{
DispatchQueue.main.async {
let authenticationViewController = self.storyboard.instantiateViewController(withIdentifier: "authenticationViewController") as! AuthenticationViewController
authenticationViewController.authenticationHandler = { (appleID, password, completionHandler) in
self.authenticate(appleID: appleID, password: password) { (result) in
completionHandler(result)
let viewController = UIHostingController(rootView: NavigationView {
ConnectAppleIDView { appleID, password, completionHandler in
self.authenticate(appleID: appleID, password: password) { (result) in
completionHandler(result)
}
} completionHandler: { result in
if let (account, session, password) = result
{
// We presented the Auth UI and the user signed in.
// In this case, we'll assume we should show the instructions again.
self.shouldShowInstructions = true
self.appleIDPassword = password
completionHandler(.success((account, session)))
}
else
{
completionHandler(.failure(OperationError.cancelled))
}
}
}
authenticationViewController.completionHandler = { (result) in
if let (account, session, password) = result
{
// We presented the Auth UI and the user signed in.
// In this case, we'll assume we should show the instructions again.
self.shouldShowInstructions = true
self.appleIDPassword = password
completionHandler(.success((account, session)))
}
else
{
completionHandler(.failure(OperationError.cancelled))
}
}
})
if !self.present(authenticationViewController)
if !self.present(viewController)
{
completionHandler(.failure(OperationError.notAuthenticated))
}
@@ -379,8 +387,8 @@ private extension AuthenticationOperation
case .success(let anisetteData):
let verificationHandler: ((@escaping (String?) -> Void) -> Void)?
if let presentingViewController = self.presentingViewController
{
// if let presentingViewController = self.presentingViewController
// {
verificationHandler = { (completionHandler) in
DispatchQueue.main.async {
let alertController = UIAlertController(title: NSLocalizedString("Please enter the 6-digit verification code that was sent to your Apple devices.", comment: ""), message: nil, preferredStyle: .alert)
@@ -406,22 +414,22 @@ private extension AuthenticationOperation
completionHandler(nil)
})
if self.navigationController.presentingViewController != nil
{
self.navigationController.present(alertController, animated: true, completion: nil)
}
else
{
presentingViewController.present(alertController, animated: true, completion: nil)
}
// if self.navigationController.presentingViewController != nil
// {
// self.navigationController.present(alertController, animated: true, completion: nil)
// }
// else
// {
// presentingViewController.present(alertController, animated: true, completion: nil)
// }
}
}
}
else
{
// No view controller to present security code alert, so don't provide verificationHandler.
verificationHandler = nil
}
// }
// else
// {
// // No view controller to present security code alert, so don't provide verificationHandler.
// verificationHandler = nil
// }
ALTAppleAPI.shared.authenticate(appleID: appleID, password: password, anisetteData: anisetteData,
verificationHandler: verificationHandler) { (account, session, error) in
@@ -452,15 +460,15 @@ private extension AuthenticationOperation
}
} else {
DispatchQueue.main.async {
let selectTeamViewController = self.storyboard.instantiateViewController(withIdentifier: "selectTeamViewController") as! SelectTeamViewController
selectTeamViewController.teams = teams
selectTeamViewController.completionHandler = completionHandler
if !self.present(selectTeamViewController)
{
return completionHandler(.failure(AuthenticationError.noTeam))
}
// let selectTeamViewController = self.storyboard.instantiateViewController(withIdentifier: "selectTeamViewController") as! SelectTeamViewController
//
// selectTeamViewController.teams = teams
// selectTeamViewController.completionHandler = completionHandler
//
// if !self.present(selectTeamViewController)
// {
// return completionHandler(.failure(AuthenticationError.noTeam))
// }
}
}
}
@@ -642,20 +650,21 @@ private extension AuthenticationOperation
func showInstructionsIfNecessary(completionHandler: @escaping (Bool) -> Void)
{
guard self.shouldShowInstructions else { return completionHandler(false) }
DispatchQueue.main.async {
let instructionsViewController = self.storyboard.instantiateViewController(withIdentifier: "instructionsViewController") as! InstructionsViewController
instructionsViewController.showsBottomButton = true
instructionsViewController.completionHandler = {
completionHandler(true)
}
if !self.present(instructionsViewController)
{
completionHandler(false)
}
}
return completionHandler(false)
// guard self.shouldShowInstructions else { return completionHandler(false) }
//
// DispatchQueue.main.async {
// let instructionsViewController = self.storyboard.instantiateViewController(withIdentifier: "instructionsViewController") as! InstructionsViewController
// instructionsViewController.showsBottomButton = true
// instructionsViewController.completionHandler = {
// completionHandler(true)
// }
//
// if !self.present(instructionsViewController)
// {
// completionHandler(false)
// }
// }
}
func showRefreshScreenIfNecessary(signer: ALTSigner, session: ALTAppleAPISession, completionHandler: @escaping (Bool) -> Void)

View File

@@ -0,0 +1,52 @@
//
// RoundedTextField.swift
// SideStore
//
// Created by Fabian Thies on 29.11.22.
// Copyright © 2022 SideStore. All rights reserved.
//
import SwiftUI
struct RoundedTextField: View {
let title: String?
let placeholder: String
@Binding var text: String
let isSecure: Bool
init(title: String?, placeholder: String, text: Binding<String>, isSecure: Bool = false) {
self.title = title
self.placeholder = placeholder
self._text = text
self.isSecure = isSecure
}
init(_ placeholder: String, text: Binding<String>, isSecure: Bool = false) {
self.init(title: nil, placeholder: placeholder, text: text, isSecure: isSecure)
}
var body: some View {
VStack(alignment: .leading, spacing: 8) {
if let title {
Text(title.uppercased())
.font(.system(size: 12))
.foregroundColor(.secondary)
.padding(.horizontal)
}
HStack(alignment: .center) {
if isSecure {
SecureField(placeholder, text: $text)
} else {
TextField(placeholder, text: $text)
}
}
.padding()
.background(
RoundedRectangle(cornerRadius: 12)
.foregroundColor(Color(.secondarySystemBackground))
)
}
}
}

View File

@@ -0,0 +1,47 @@
//
// FilledButtonStyle.swift
// SideStore
//
// Created by Fabian Thies on 29.11.22.
// Copyright © 2022 SideStore. All rights reserved.
//
import SwiftUI
struct FilledButtonStyle: ButtonStyle {
var isLoading: Bool = false
func makeBody(configuration: Configuration) -> some View {
ZStack {
configuration.label
.opacity(isLoading ? 0 : 1)
if isLoading {
ProgressView()
.progressViewStyle(CircularProgressViewStyle())
}
}
.foregroundColor(.white)
.multilineTextAlignment(.center)
.frame(maxWidth: .infinity)
.padding()
.background(
RoundedRectangle(cornerRadius: 12)
.foregroundColor(.accentColor)
)
.opacity(configuration.isPressed || isLoading ? 0.7 : 1)
.disabled(isLoading)
}
}
struct FilledButtonStyle_Previews: PreviewProvider {
static var previews: some View {
SwiftUI.Button {
} label: {
Label("Test Button", systemImage: "testtube.2")
.buttonStyle(FilledButtonStyle())
}
}
}

View File

@@ -0,0 +1,109 @@
//
// ConnectAppleIDView.swift
// SideStore
//
// Created by Fabian Thies on 29.11.22.
// Copyright © 2022 SideStore. All rights reserved.
//
import SwiftUI
import AltSign
struct ConnectAppleIDView: View {
typealias AuthenticationHandler = (String, String, @escaping (Result<(ALTAccount, ALTAppleAPISession), Error>) -> Void) -> Void
typealias CompletionHandler = ((ALTAccount, ALTAppleAPISession, String)?) -> Void
@Environment(\.dismiss)
private var dismiss
var authenticationHandler: AuthenticationHandler?
var completionHandler: CompletionHandler?
@State var email: String = ""
@State var password: String = ""
@State var isLoading: Bool = false
var isFormValid: Bool {
!email.isEmpty && !password.isEmpty
}
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 32) {
Text("Sign in with your Apple ID to get started.")
VStack(spacing: 16) {
RoundedTextField(title: "Apple ID", placeholder: "user@sidestore.io", text: $email)
RoundedTextField(title: "Password", placeholder: "••••••", text: $password, isSecure: true)
}
SwiftUI.Button(action: signIn) {
Text("Sign in")
.bold()
}
.buttonStyle(FilledButtonStyle(isLoading: isLoading))
.disabled(!isFormValid)
Spacer()
VStack(alignment: .leading) {
Text("Why do we need this?")
.bold()
Text("Your Apple ID is used to configure apps so they can be installed on this device. Your credentials will be stored securely in this device's Keychain and sent only to Apple for authentication.")
}
.padding()
.background(
RoundedRectangle(cornerRadius: 12)
.foregroundColor(Color(.secondarySystemBackground))
)
}
.padding(.horizontal)
}
.frame(maxWidth: .infinity)
.navigationTitle("Connect your Apple ID")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
SwiftUI.Button(action: self.cancel) {
Text("Cancel")
}
}
}
}
func signIn() {
self.isLoading = true
self.authenticationHandler?(email, password) { (result) in
defer {
self.isLoading = false
}
switch result
{
case .failure(ALTAppleAPIError.requiresTwoFactorAuthentication):
// Ignore
break
case .failure(let error as NSError):
let error = error.withLocalizedFailure(NSLocalizedString("Failed to Log In", comment: ""))
print(error)
case .success((let account, let session)):
self.completionHandler?((account, session, password))
}
}
}
func cancel() {
self.completionHandler?(nil)
// self.dismiss()
}
}
struct ConnectAppleIDView_Previews: PreviewProvider {
static var previews: some View {
ConnectAppleIDView()
}
}

View File

@@ -13,49 +13,74 @@ import Intents
struct SettingsView: View {
var connectedAppleID: Team? {
DatabaseManager.shared.activeTeam()
}
@SwiftUI.FetchRequest(sortDescriptors: [], predicate: NSPredicate(format: "%K == YES", #keyPath(Team.isActiveTeam)))
var connectedTeams: FetchedResults<Team>
@AppStorage("isBackgroundRefreshEnabled")
var isBackgroundRefreshEnabled: Bool = true
@State var isShowingConnectAppleIDView = false
@State var isShowingAddShortcutView = false
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
var body: some View {
List {
Section {
if let team = DatabaseManager.shared.activeTeam() {
if let connectedAppleID = connectedTeams.first {
HStack {
Text("Name")
.foregroundColor(.secondary)
Spacer()
Text(team.name)
Text(connectedAppleID.name)
}
HStack {
Text("E-Mail")
.foregroundColor(.secondary)
Spacer()
Text(team.account.appleID)
Text(connectedAppleID.account.appleID)
}
HStack {
Text("Type")
.foregroundColor(.secondary)
Spacer()
Text(team.type.localizedDescription)
Text(connectedAppleID.type.localizedDescription)
}
} else {
SwiftUI.Button {
self.connectAppleID()
} label: {
Text("Connect your Apple ID")
}
}
} header: {
HStack {
Text("Connected Apple ID")
Spacer()
SwiftUI.Button {
} label: {
Text("Sign Out")
.font(.callout)
.bold()
if !connectedTeams.isEmpty {
HStack {
Text("Connected Apple ID")
Spacer()
SwiftUI.Button {
self.disconnectAppleID()
} label: {
Text("Sign Out")
.font(.callout)
.bold()
}
}
}
} footer: {
VStack(spacing: 4) {
Text("Your Apple ID is required to sign the apps you install with SideStore.")
Text("Your credentials are only sent to Apple's servers and are not accessible by the SideStore Team. Once successfully logged in, the login details are stored securely on your device.")
}
}
Section {
@@ -63,16 +88,14 @@ struct SettingsView: View {
Text("Background Refresh")
})
if #available(iOS 14.0, *) {
SwiftUI.Button {
self.isShowingAddShortcutView = true
} label: {
Text("Add to Siri...")
}
.sheet(isPresented: self.$isShowingAddShortcutView) {
if let shortcut = INShortcut(intent: INInteraction.refreshAllApps().intent) {
SiriShortcutSetupView(shortcut: shortcut)
}
SwiftUI.Button {
self.isShowingAddShortcutView = true
} label: {
Text("Add to Siri...")
}
.sheet(isPresented: self.$isShowingAddShortcutView) {
if let shortcut = INShortcut(intent: INInteraction.refreshAllApps().intent) {
SiriShortcutSetupView(shortcut: shortcut)
}
}
} header: {
@@ -114,7 +137,7 @@ struct SettingsView: View {
Section {
} footer: {
Text("SideStore 1.0.0")
Text("SideStore \(appVersion)")
.multilineTextAlignment(.center)
.frame(maxWidth: .infinity)
}
@@ -135,6 +158,42 @@ struct SettingsView: View {
}
// var appleIDSection: some View {
//
// }
func connectAppleID() {
AppManager.shared.authenticate(presentingViewController: nil) { (result) in
DispatchQueue.main.async {
switch result
{
case .failure(OperationError.cancelled):
// Ignore
break
case .failure(let error):
NotificationManager.shared.reportError(error: error)
case .success: break
}
}
}
}
func disconnectAppleID() {
DatabaseManager.shared.signOut { (error) in
DispatchQueue.main.async {
if let error = error
{
NotificationManager.shared.reportError(error: error)
}
}
}
}
func switchToUIKit() {
let storyboard = UIStoryboard(name: "Main", bundle: .main)
let rootVC = storyboard.instantiateViewController(withIdentifier: "tabBarController") as! TabBarController