2022-11-23 22:34:02 +01:00
//
// S e t t i n g s V i e w . s w i f t
// S i d e S t o r e U I
//
// C r e a t e d b y F a b i a n T h i e s o n 1 8 . 1 1 . 2 2 .
// C o p y r i g h t © 2 0 2 2 F a b i a n T h i e s . A l l r i g h t s r e s e r v e d .
//
import SwiftUI
2022-11-27 00:26:15 +01:00
import AsyncImage
2022-12-23 15:21:16 +01:00
import SFSafeSymbols
2023-02-13 18:56:34 +01:00
import LocalConsole
2022-11-23 22:34:02 +01:00
import AltStoreCore
import Intents
struct SettingsView : View {
2022-12-12 19:12:38 +01:00
var connectedAppleID : Team ? {
DatabaseManager . shared . activeTeam ( )
}
@ SwiftUI . FetchRequest ( sortDescriptors : [ ] , predicate : NSPredicate ( format : " %K == YES " , # keyPath ( Team . isActiveTeam ) ) )
var connectedTeams : FetchedResults < Team >
2022-11-23 22:34:02 +01:00
@ AppStorage ( " isBackgroundRefreshEnabled " )
var isBackgroundRefreshEnabled : Bool = true
2022-12-12 19:12:38 +01:00
@ State var isShowingConnectAppleIDView = false
2022-11-23 22:34:02 +01:00
@ State var isShowingAddShortcutView = false
2023-02-04 14:29:02 +01:00
@ State var isShowingFeedbackMailView = false
@ State var isShowingResetPairingFileConfirmation = false
2023-01-31 22:30:21 +01:00
@ State var externalURLToShow : URL ?
2022-11-23 22:34:02 +01:00
2022-12-12 19:12:38 +01:00
let appVersion = Bundle . main . infoDictionary ? [ " CFBundleShortVersionString " ] as ? String ? ? " "
2022-11-23 22:34:02 +01:00
var body : some View {
List {
Section {
2022-12-12 19:12:38 +01:00
if let connectedAppleID = connectedTeams . first {
2022-11-23 22:34:02 +01:00
HStack {
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . ConnectedAppleID . name )
2022-11-23 22:34:02 +01:00
. foregroundColor ( . secondary )
Spacer ( )
2022-12-12 19:12:38 +01:00
Text ( connectedAppleID . name )
2022-11-23 22:34:02 +01:00
}
HStack {
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . ConnectedAppleID . eMail )
2022-11-23 22:34:02 +01:00
. foregroundColor ( . secondary )
Spacer ( )
2022-12-12 19:12:38 +01:00
Text ( connectedAppleID . account . appleID )
2022-11-23 22:34:02 +01:00
}
HStack {
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . ConnectedAppleID . type )
2022-11-23 22:34:02 +01:00
. foregroundColor ( . secondary )
Spacer ( )
2022-12-12 19:12:38 +01:00
Text ( connectedAppleID . type . localizedDescription )
2022-11-23 22:34:02 +01:00
}
2022-12-12 19:12:38 +01:00
} else {
2022-11-23 22:34:02 +01:00
SwiftUI . Button {
2022-12-12 19:12:38 +01:00
self . connectAppleID ( )
2022-11-23 22:34:02 +01:00
} label : {
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . connectAppleID )
2022-12-12 19:12:38 +01:00
}
}
} header : {
if ! connectedTeams . isEmpty {
HStack {
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . ConnectedAppleID . text )
2022-12-12 19:12:38 +01:00
Spacer ( )
SwiftUI . Button {
self . disconnectAppleID ( )
} label : {
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . ConnectedAppleID . signOut )
2022-12-12 19:12:38 +01:00
. font ( . callout )
. bold ( )
}
2022-11-23 22:34:02 +01:00
}
}
2022-12-12 19:12:38 +01:00
} footer : {
2023-01-16 19:03:33 +01:00
VStack ( alignment : . leading , spacing : 4 ) {
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . ConnectedAppleID . Footer . p1 )
2022-12-12 19:12:38 +01:00
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . ConnectedAppleID . Footer . p2 )
2022-12-12 19:12:38 +01:00
}
2022-11-23 22:34:02 +01:00
}
Section {
Toggle ( isOn : self . $ isBackgroundRefreshEnabled , label : {
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . backgroundRefresh )
2022-11-23 22:34:02 +01:00
} )
2022-12-12 19:12:38 +01:00
SwiftUI . Button {
self . isShowingAddShortcutView = true
} label : {
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . addToSiri )
2022-12-12 19:12:38 +01:00
}
. sheet ( isPresented : self . $ isShowingAddShortcutView ) {
if let shortcut = INShortcut ( intent : INInteraction . refreshAllApps ( ) . intent ) {
SiriShortcutSetupView ( shortcut : shortcut )
2022-11-23 22:34:02 +01:00
}
}
} header : {
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . refreshingApps )
2022-11-23 22:34:02 +01:00
} footer : {
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . refreshingAppsFooter )
2022-11-23 22:34:02 +01:00
}
2023-01-31 22:30:21 +01:00
2022-11-23 22:34:02 +01:00
Section {
2023-01-31 22:30:21 +01:00
SwiftUI . Button {
self . externalURLToShow = URL ( string : " https://sidestore.io " ) !
} label : {
HStack {
Text ( " Developers " )
. foregroundColor ( . secondary )
Spacer ( )
Text ( " SideStore Team " )
Image ( systemSymbol : . chevronRight )
. foregroundColor ( . secondary )
}
2022-11-23 22:34:02 +01:00
}
2023-01-31 22:30:21 +01:00
. foregroundColor ( . primary )
2022-11-23 22:34:02 +01:00
2023-01-31 22:30:21 +01:00
SwiftUI . Button {
self . externalURLToShow = URL ( string : " https://fabian-thies.de " ) !
2022-11-23 22:34:02 +01:00
} label : {
HStack {
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . swiftUIRedesign )
2022-11-23 22:34:02 +01:00
. foregroundColor ( . secondary )
Spacer ( )
Text ( " fabianthdev " )
2023-01-31 22:30:21 +01:00
Image ( systemSymbol : . chevronRight )
. foregroundColor ( . secondary )
2022-11-23 22:34:02 +01:00
}
}
2023-01-31 22:30:21 +01:00
. foregroundColor ( . primary )
NavigationLink {
LicensesView ( )
} label : {
Text ( " Licenses " )
}
2022-11-23 22:34:02 +01:00
} header : {
2022-12-24 21:06:28 -07:00
Text ( L10n . SettingsView . credits )
2022-11-23 22:34:02 +01:00
}
2023-01-31 22:30:21 +01:00
Section {
2023-02-04 14:29:02 +01:00
NavigationLink ( " Show Error Log " ) {
ErrorLogView ( )
2023-01-31 22:30:21 +01:00
}
2023-02-04 14:29:02 +01:00
NavigationLink ( " Show Refresh Attempts " ) {
RefreshAttemptsView ( )
2023-01-31 22:30:21 +01:00
}
2023-02-04 13:07:04 +01:00
2023-02-13 18:56:34 +01:00
SwiftUI . Button ( " Toggle Console " ) {
LCManager . shared . isVisible . toggle ( )
}
2023-02-04 14:29:02 +01:00
if MailComposeView . canSendMail {
SwiftUI . Button ( " Send Feedback " ) {
self . isShowingFeedbackMailView = true
}
. sheet ( isPresented : self . $ isShowingFeedbackMailView ) {
MailComposeView ( recipients : [ " support@sidestore.io " ] ,
subject : " SideStore Beta \( appVersion ) Feedback " ) {
NotificationManager . shared . showNotification ( title : " Thank you for your feedback! " )
} onError : { error in
NotificationManager . shared . reportError ( error : error )
}
. ignoresSafeArea ( )
}
}
SwiftUI . Button ( L10n . SettingsView . switchToUIKit , action : self . switchToUIKit )
SwiftUI . Button ( " Advanced Settings " , action : self . showAdvancedSettings )
SwiftUI . Button ( L10n . SettingsView . resetImageCache , action : self . resetImageCache )
. foregroundColor ( . red )
SwiftUI . Button ( " Reset Pairing File " ) {
self . isShowingResetPairingFileConfirmation = true
}
. foregroundColor ( . red )
. actionSheet ( isPresented : self . $ isShowingResetPairingFileConfirmation ) {
ActionSheet ( title : Text ( " Are you sure to reset the pairing file? " ) , message : Text ( " You can reset the pairing file when you cannot sideload apps or enable JIT. SideStore will close when the file has been deleted. " ) , buttons : [
. destructive ( Text ( " Delete and Reset " ) , action : self . resetPairingFile ) ,
. cancel ( )
] )
2023-02-04 13:07:04 +01:00
}
2023-01-31 22:30:21 +01:00
} header : {
Text ( L10n . SettingsView . debug )
}
2022-11-23 22:34:02 +01:00
Section {
} footer : {
2022-12-12 19:12:38 +01:00
Text ( " SideStore \( appVersion ) " )
2022-11-23 22:34:02 +01:00
. multilineTextAlignment ( . center )
. frame ( maxWidth : . infinity )
}
}
. listStyle ( InsetGroupedListStyle ( ) )
2022-12-24 21:06:28 -07:00
. navigationTitle ( L10n . SettingsView . title )
2022-11-23 22:34:02 +01:00
. toolbar {
ToolbarItem ( placement : . navigationBarTrailing ) {
SwiftUI . Button {
} label : {
2022-12-23 15:21:16 +01:00
Image ( systemSymbol : . personCropCircle )
2022-11-23 22:34:02 +01:00
. imageScale ( . large )
}
}
}
2023-01-31 22:30:21 +01:00
. sheet ( item : $ externalURLToShow ) { url in
SafariView ( url : url )
}
2022-11-23 22:34:02 +01:00
}
2022-12-12 19:12:38 +01:00
// v a r a p p l e I D S e c t i o n : s o m e V i e w {
//
// }
func connectAppleID ( ) {
2023-02-04 13:07:04 +01:00
guard let rootViewController = UIApplication . shared . keyWindow ? . rootViewController else {
return
}
AppManager . shared . authenticate ( presentingViewController : rootViewController ) { ( result ) in
2022-12-12 19:12:38 +01:00
DispatchQueue . main . async {
switch result
{
case . failure ( OperationError . cancelled ) :
// I g n o r e
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 )
}
}
}
}
2022-11-23 22:34:02 +01:00
func switchToUIKit ( ) {
let storyboard = UIStoryboard ( name : " Main " , bundle : . main )
let rootVC = storyboard . instantiateViewController ( withIdentifier : " tabBarController " ) as ! TabBarController
UIApplication . shared . keyWindow ? . rootViewController = rootVC
}
2022-11-27 00:26:15 +01:00
func resetImageCache ( ) {
do {
let url = try FileManager . default . url (
for : . cachesDirectory ,
in : . userDomainMask ,
appropriateFor : nil ,
create : true )
try FileManager . default . removeItem ( at : url . appendingPathComponent ( " com.zeu.cache " , isDirectory : true ) )
} catch let error {
fatalError ( " \( error ) " )
}
}
2023-02-04 14:29:02 +01:00
func resetPairingFile ( ) {
let filename = " ALTPairingFile.mobiledevicepairing "
let fileURL = FileManager . default . documentsDirectory . appendingPathComponent ( filename )
// D e l e t e t h e p a i r i n g f i l e i f i t e x i s t s
if FileManager . default . fileExists ( atPath : fileURL . path ) {
do {
try FileManager . default . removeItem ( at : fileURL )
print ( " Pairing file deleted successfully. " )
} catch {
print ( " Failed to delete pairing file: " , error )
}
}
// C l o s e a n d e x i t S i d e S t o r e
UIApplication . shared . perform ( #selector ( URLSessionTask . suspend ) )
DispatchQueue . main . asyncAfter ( deadline : . now ( ) . advanced ( by : . milliseconds ( 500 ) ) ) {
exit ( 0 )
}
}
func showAdvancedSettings ( ) {
// C r e a t e t h e U R L t h a t d e e p l i n k s t o o u r a p p ' s c u s t o m s e t t i n g s .
guard let url = URL ( string : UIApplication . openSettingsURLString ) else {
return
}
// A s k t h e s y s t e m t o o p e n t h a t U R L .
UIApplication . shared . open ( url )
}
2022-11-23 22:34:02 +01:00
}
struct SettingsView_Previews : PreviewProvider {
static var previews : some View {
2023-01-16 19:03:33 +01:00
NavigationView {
SettingsView ( )
}
2022-11-23 22:34:02 +01:00
}
}
2022-11-27 00:26:15 +01:00