@@ -14,13 +14,7 @@ import AltSign
1414import LaunchAtLogin
1515import Sparkle
1616
17- #if STAGING
18- private let altstoreAppURL = URL ( string: " https://f000.backblazeb2.com/file/altstore-staging/altstore.ipa " ) !
19- #elseif BETA
20- private let altstoreAppURL = URL ( string: " https://cdn.altstore.io/file/altstore/altstore-beta.ipa " ) !
21- #else
22- private let altstoreAppURL = URL ( string: " https://cdn.altstore.io/file/altstore/altstore.ipa " ) !
23- #endif
17+ private let altstoreAppURL = URL ( string: " https://github.com/SideStore/SideStore/releases/download/0.1.1/SideStore.ipa " ) !
2418
2519extension ALTDevice : MenuDisplayable { }
2620
@@ -44,9 +38,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
4438 @IBOutlet private var installMailPluginMenuItem : NSMenuItem !
4539 @IBOutlet private var installAltStoreMenuItem : NSMenuItem !
4640 @IBOutlet private var sideloadAppMenuItem : NSMenuItem !
47-
48- private weak var authenticationAppleIDTextField : NSTextField ?
49- private weak var authenticationPasswordTextField : NSSecureTextField ?
41+ @IBOutlet private var logInMenuItem : NSMenuItem !
5042
5143 private var connectedDevicesMenuController : MenuController < ALTDevice > !
5244 private var sideloadIPAConnectedDevicesMenuController : MenuController < ALTDevice > !
@@ -125,6 +117,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
125117 self . installMailPlugin ( )
126118 }
127119 }
120+
121+ setupLoginMenuItem ( )
128122 }
129123
130124 func applicationWillTerminate( _ aNotification: Notification )
@@ -197,48 +191,32 @@ private extension AppDelegate
197191
198192 func installApplication( at url: URL , to device: ALTDevice )
199193 {
200- let alert = NSAlert ( )
201- alert. messageText = NSLocalizedString ( " Please enter your Apple ID and password. " , comment: " " )
202- alert. informativeText = NSLocalizedString ( " Your Apple ID and password are not saved and are only sent to Apple for authentication. " , comment: " " )
203-
204- let textFieldSize = NSSize ( width: 300 , height: 22 )
205-
206- let appleIDTextField = NSTextField ( frame: NSRect ( x: 0 , y: 0 , width: textFieldSize. width, height: textFieldSize. height) )
207- appleIDTextField. delegate = self
208- appleIDTextField. translatesAutoresizingMaskIntoConstraints = false
209- appleIDTextField. placeholderString = NSLocalizedString ( " Apple ID " , comment: " " )
210- alert. window. initialFirstResponder = appleIDTextField
211- self . authenticationAppleIDTextField = appleIDTextField
212-
213- let passwordTextField = NSSecureTextField ( frame: NSRect ( x: 0 , y: 0 , width: textFieldSize. width, height: textFieldSize. height) )
214- passwordTextField. delegate = self
215- passwordTextField. translatesAutoresizingMaskIntoConstraints = false
216- passwordTextField. placeholderString = NSLocalizedString ( " Password " , comment: " " )
217- self . authenticationPasswordTextField = passwordTextField
218-
219- appleIDTextField. nextKeyView = passwordTextField
220-
221- let stackView = NSStackView ( frame: NSRect ( x: 0 , y: 0 , width: textFieldSize. width, height: textFieldSize. height * 2 ) )
222- stackView. orientation = . vertical
223- stackView. distribution = . equalSpacing
224- stackView. spacing = 0
225- stackView. addArrangedSubview ( appleIDTextField)
226- stackView. addArrangedSubview ( passwordTextField)
227- alert. accessoryView = stackView
228-
229- alert. addButton ( withTitle: NSLocalizedString ( " Install " , comment: " " ) )
230- alert. addButton ( withTitle: NSLocalizedString ( " Cancel " , comment: " " ) )
231-
232- self . authenticationAlert = alert
233- self . validate ( )
234-
235- NSRunningApplication . current. activate ( options: . activateIgnoringOtherApps)
236-
237- let response = alert. runModal ( )
238- guard response == . alertFirstButtonReturn else { return }
239-
240- let username = appleIDTextField. stringValue
241- let password = passwordTextField. stringValue
194+ let username : String
195+ let password : String
196+
197+ if let _username = try ? Keychain . shared. getValue ( for: . appleIDEmail) ,
198+ let _password = try ? Keychain . shared. getValue ( for: . appleIDPassword) {
199+ username = _username
200+ password = _password
201+ } else {
202+ let alert = AppleIDAuthenticationAlert ( )
203+ self . authenticationAlert = alert
204+
205+ NSRunningApplication . current. activate ( options: . activateIgnoringOtherApps)
206+
207+ let didTapContinue = alert. display ( )
208+ guard didTapContinue else { return }
209+
210+ username = alert. appleIDValue. trimmingCharacters ( in: . whitespacesAndNewlines)
211+ password = alert. passwordValue. trimmingCharacters ( in: . whitespacesAndNewlines)
212+
213+ do {
214+ try Keychain . shared. setValue ( username. isEmpty ? nil : username, for: . appleIDEmail)
215+ try Keychain . shared. setValue ( password. isEmpty ? nil : password, for: . appleIDPassword)
216+ } catch {
217+ print ( " AppleID Auth: Error saving credentials: \( error) " )
218+ }
219+ }
242220
243221 func finish( _ result: Result < ALTApplication , Error > )
244222 {
@@ -453,6 +431,58 @@ private extension AppDelegate
453431 }
454432}
455433
434+ // MARK: - AppDelegate+loginMenuItem
435+
436+ private extension AppDelegate {
437+ private func setupLoginMenuItem( ) {
438+ do {
439+ let email = try Keychain . shared. getValue ( for: . appleIDEmail)
440+ logInMenuItem. title = " Log out ( \( email) ) "
441+ logInMenuItem. action = #selector( logoutFromAppleID)
442+ } catch {
443+ print ( " Error getting stored AppleID credentials: \( error) " )
444+ logInMenuItem. title = " Log in... "
445+ logInMenuItem. action = #selector( loginToAppleID)
446+ }
447+ }
448+
449+ @objc private func loginToAppleID( ) {
450+ let alert = AppleIDAuthenticationAlert ( )
451+
452+ NSRunningApplication . current. activate ( options: . activateIgnoringOtherApps)
453+ let didTapContinue = alert. display ( )
454+ guard didTapContinue else { return }
455+
456+ let username = alert. appleIDValue. trimmingCharacters ( in: . whitespacesAndNewlines)
457+ let password = alert. passwordValue. trimmingCharacters ( in: . whitespacesAndNewlines)
458+
459+ guard !username. isEmpty && !password. isEmpty else {
460+ print ( " AppleID Auth: Username and/or password was empty. " )
461+ return
462+ }
463+
464+ do {
465+ try Keychain . shared. setValue ( username, for: . appleIDEmail)
466+ try Keychain . shared. setValue ( password, for: . appleIDPassword)
467+ } catch {
468+ let errorAlert = NSAlert ( error: error)
469+ NSRunningApplication . current. activate ( options: . activateIgnoringOtherApps)
470+ errorAlert. runModal ( )
471+
472+ print ( " AppleID Auth: Error saving credentials: \( error) " )
473+ }
474+
475+ setupLoginMenuItem ( )
476+ }
477+
478+ @objc private func logoutFromAppleID( ) {
479+ print ( " Removing AppleID credentials! " )
480+ try ? Keychain . shared. setValue ( nil , for: . appleIDEmail)
481+ try ? Keychain . shared. setValue ( nil , for: . appleIDPassword)
482+ setupLoginMenuItem ( )
483+ }
484+ }
485+
456486extension AppDelegate : NSMenuDelegate
457487{
458488 func menuWillOpen( _ menu: NSMenu )
@@ -571,38 +601,6 @@ extension AppDelegate: NSMenuDelegate
571601 }
572602}
573603
574- extension AppDelegate : NSTextFieldDelegate
575- {
576- func controlTextDidChange( _ obj: Notification )
577- {
578- self . validate ( )
579- }
580-
581- func controlTextDidEndEditing( _ obj: Notification )
582- {
583- self . validate ( )
584- }
585-
586- private func validate( )
587- {
588- guard
589- let appleID = self . authenticationAppleIDTextField? . stringValue. trimmingCharacters ( in: . whitespacesAndNewlines) ,
590- let password = self . authenticationPasswordTextField? . stringValue. trimmingCharacters ( in: . whitespacesAndNewlines)
591- else { return }
592-
593- if appleID. isEmpty || password. isEmpty
594- {
595- self . authenticationAlert? . buttons. first? . isEnabled = false
596- }
597- else
598- {
599- self . authenticationAlert? . buttons. first? . isEnabled = true
600- }
601-
602- self . authenticationAlert? . layout ( )
603- }
604- }
605-
606604extension AppDelegate : UNUserNotificationCenterDelegate
607605{
608606 func userNotificationCenter( _ center: UNUserNotificationCenter , willPresent notification: UNNotification , withCompletionHandler completionHandler: @escaping ( UNNotificationPresentationOptions ) -> Void )
0 commit comments