2019-06-14 00:53:17 +00:00
// A d v a n c e d P r e f s V i e w . s w i f t
// T u s k e r
//
// C r e a t e d b y S h a d o w f a c t s o n 6 / 1 3 / 1 9 .
// C o p y r i g h t © 2 0 1 9 S h a d o w f a c t s . A l l r i g h t s r e s e r v e d .
//
import SwiftUI
import Pachyderm
2022-10-29 14:18:38 +00:00
import CoreData
2022-12-31 16:24:42 +00:00
import CloudKit
2019-06-14 00:53:17 +00:00
struct AdvancedPrefsView : View {
2019-11-15 00:53:00 +00:00
@ ObservedObject var preferences = Preferences . shared
2022-11-28 19:05:35 +00:00
@ State private var imageCacheSize : Int64 = 0
@ State private var mastodonCacheSize : Int64 = 0
2022-12-31 16:24:42 +00:00
@ State private var cloudKitStatus : CKAccountStatus ?
2022-11-28 19:05:35 +00:00
2019-06-14 00:53:17 +00:00
var body : some View {
List {
2019-07-28 01:43:08 +00:00
formattingSection
2022-12-31 16:24:42 +00:00
cloudKitSection
2022-10-30 22:17:53 +00:00
errorReportingSection
2020-05-13 22:58:11 +00:00
cachingSection
2020-09-16 00:46:49 +00:00
}
2023-02-03 04:29:44 +00:00
. listStyle ( . insetGrouped )
. appGroupedScrollBackgroundIfAvailable ( )
2020-09-16 00:46:49 +00:00
. navigationBarTitle ( Text ( " Advanced " ) )
2019-07-28 01:43:08 +00:00
}
var formattingFooter : some View {
2022-11-22 16:39:47 +00:00
var s : AttributedString = " This option is only supported with Pleroma and some compatible Mastodon instances (such as Glitch). \n "
2022-11-02 02:43:02 +00:00
if let account = LocalData . shared . getMostRecentAccount ( ) {
let mastodonController = MastodonController . getForAccount ( account )
// s h o u l d n ' t n e e d t o l o a d t h e i n s t a n c e h e r e , b e c a u s e l o a d i n g i t i s k i c k e d o f f m y t h e s c e n e d e l e g a t e
if ! mastodonController . instanceFeatures . probablySupportsMarkdown {
var warning = AttributedString ( " \( account . instanceURL . host ! ) does not appear to support formatting. Using formatting symbols may not have an effect. " )
warning [ AttributeScopes . SwiftUIAttributes . FontAttribute . self ] = . caption . bold ( )
s += warning
}
}
return Text ( s ) . lineLimit ( nil )
2019-07-28 01:43:08 +00:00
}
var formattingSection : some View {
Section ( footer : formattingFooter ) {
2019-11-15 00:53:00 +00:00
Picker ( selection : $ preferences . statusContentType , label : Text ( " Post Content Type " ) ) {
2019-07-28 01:43:08 +00:00
ForEach ( StatusContentType . allCases , id : \ . self ) { type in
Text ( type . displayName ) . tag ( type )
} // . n a v i g a t i o n B a r T i t l e ( " P o s t C o n t e n t T y p e " )
// s e e F B 6 8 3 8 2 9 1
2019-06-14 00:53:17 +00:00
}
2019-07-28 01:43:08 +00:00
}
2023-02-03 04:29:44 +00:00
. listRowBackground ( Color . appGroupedCellBackground )
2019-07-28 01:43:08 +00:00
}
2022-12-31 16:24:42 +00:00
var cloudKitSection : some View {
Section {
HStack {
Text ( " iCloud Status " )
Spacer ( )
switch cloudKitStatus {
case nil :
EmptyView ( )
case . available :
Text ( " Available " )
case . couldNotDetermine :
Text ( " Could not determine " )
case . noAccount :
Text ( " No account " )
case . restricted :
Text ( " Restricted " )
case . temporarilyUnavailable :
Text ( " Temporarily Unavailable " )
@ unknown default :
Text ( String ( describing : cloudKitStatus ! ) )
}
}
2023-02-03 04:29:44 +00:00
}
. listRowBackground ( Color . appGroupedCellBackground )
. task {
2022-12-31 16:24:42 +00:00
CKContainer . default ( ) . accountStatus { status , error in
if let error {
Logging . general . error ( " Unable to get CloudKit status: \( String ( describing : error ) ) " )
} else {
self . cloudKitStatus = status
}
}
}
}
2022-10-30 22:17:53 +00:00
var errorReportingSection : some View {
Section {
Toggle ( " Report Errors Automatically " , isOn : $ preferences . reportErrorsAutomatically )
} footer : {
var privacyPolicy : AttributedString = " Privacy Policy "
let _ = privacyPolicy . link = URL ( string : " https://vaccor.space/tusker#privacy " ) !
if preferences . reportErrorsAutomatically {
Text ( AttributedString ( " App crashes and errors will be automatically reported to the developer. You may be prompted to add additional information. \n " ) + privacyPolicy )
. lineLimit ( nil )
} else {
Text ( AttributedString ( " Errors will not be reported automatically. When a crash occurs, you may be asked to report it manually. \n " ) + privacyPolicy )
. lineLimit ( nil )
}
}
2023-02-03 04:29:44 +00:00
. listRowBackground ( Color . appGroupedCellBackground )
2022-10-30 22:17:53 +00:00
}
2020-05-13 22:58:11 +00:00
var cachingSection : some View {
2022-11-28 19:05:35 +00:00
Section {
2020-05-13 22:58:11 +00:00
Button ( action : clearCache ) {
2020-09-12 14:49:08 +00:00
Text ( " Clear Mastodon Cache " )
} . foregroundColor ( . red )
Button ( action : clearImageCaches ) {
Text ( " Clear Image Caches " )
2020-05-13 22:58:11 +00:00
} . foregroundColor ( . red )
2022-11-28 19:05:35 +00:00
} header : {
Text ( " Caching " )
} footer : {
var s : AttributedString = " Clearing caches will restart the app. "
if imageCacheSize != 0 {
s += AttributedString ( " \n Image cache size: \( ByteCountFormatter ( ) . string ( fromByteCount : imageCacheSize ) ) " )
}
if mastodonCacheSize != 0 {
s += AttributedString ( " \n Mastodon cache size: \( ByteCountFormatter ( ) . string ( fromByteCount : mastodonCacheSize ) ) " )
}
return Text ( s )
2023-02-03 04:29:44 +00:00
}
. listRowBackground ( Color . appGroupedCellBackground )
. task {
2022-11-28 19:05:35 +00:00
imageCacheSize = [
ImageCache . avatars ,
. headers ,
. attachments ,
. emojis ,
] . map {
$0 . getDiskSizeInBytes ( ) ? ? 0
} . reduce ( 0 , + )
mastodonCacheSize = LocalData . shared . accounts . map {
let descriptions = MastodonController . getForAccount ( $0 ) . persistentContainer . persistentStoreDescriptions
return descriptions . map {
guard let url = $0 . url else {
return 0
}
return FileManager . default . recursiveSize ( url : url ) ? ? 0
} . reduce ( 0 , + )
} . reduce ( 0 , + )
2020-05-13 22:58:11 +00:00
}
}
2020-09-12 14:49:08 +00:00
private func clearCache ( ) {
2020-05-13 22:58:11 +00:00
for account in LocalData . shared . accounts {
let controller = MastodonController . getForAccount ( account )
2022-10-29 14:18:38 +00:00
let container = controller . persistentContainer
do {
let statusesReq = NSBatchDeleteRequest ( fetchRequest : StatusMO . fetchRequest ( ) )
try container . viewContext . execute ( statusesReq )
let accountsReq = NSBatchDeleteRequest ( fetchRequest : AccountMO . fetchRequest ( ) )
try container . viewContext . execute ( accountsReq )
let relationshipsReq = NSBatchDeleteRequest ( fetchRequest : RelationshipMO . fetchRequest ( ) )
try container . viewContext . execute ( relationshipsReq )
} catch {
Logging . general . error ( " Error while clearing Mastodon cache: \( String ( describing : error ) , privacy : . public ) " )
2020-05-13 22:58:11 +00:00
}
}
2020-09-12 14:49:08 +00:00
resetUI ( )
}
private func clearImageCaches ( ) {
[
ImageCache . avatars ,
ImageCache . headers ,
ImageCache . attachments ,
ImageCache . emojis ,
] . forEach {
try ! $0 . reset ( )
}
resetUI ( )
}
private func resetUI ( ) {
2020-05-13 22:58:11 +00:00
let mostRecent = LocalData . shared . getMostRecentAccount ( ) !
NotificationCenter . default . post ( name : . activateAccount , object : nil , userInfo : [ " account " : mostRecent ] )
}
2019-07-28 01:43:08 +00:00
}
extension StatusContentType {
var displayName : String {
switch self {
case . plain :
return " Plain "
case . markdown :
return " Markdown "
case . html :
return " HTML "
}
2019-06-14 00:53:17 +00:00
}
}
#if DEBUG
struct AdvancedPrefsView_Previews : PreviewProvider {
static var previews : some View {
AdvancedPrefsView ( )
}
}
#endif