@ -17,6 +17,7 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
public let state : TableDataState < Section , TableItem > = TableDataState ( )
public let observableState : ObservableTableSourceState < Section , TableItem > = ObservableTableSourceState ( )
private var showAdvancedLogging : Bool = false
private var databaseKeyEncryptionPassword : String = " "
// MARK: - I n i t i a l i z a t i o n
@ -29,6 +30,7 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
public enum Section : SessionTableSection {
case developerMode
case logging
case network
case disappearingMessages
case groups
@ -37,6 +39,7 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
var title : String ? {
switch self {
case . developerMode : return nil
case . logging : return " Logging "
case . network : return " Network "
case . disappearingMessages : return " Disappearing Messages "
case . groups : return " Groups "
@ -52,9 +55,13 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
}
}
public enum TableItem : Differentiable , CaseIterable {
public enum TableItem : Hashable , Differentiable , CaseIterable {
case developerMode
case defaultLogLevel
case advancedLogging
case loggingCategory ( String )
case serviceNetwork
case resetSnodeCache
@ -71,6 +78,70 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
case updatedGroupsAllowInviteById
case exportDatabase
// MARK: - C o n f o r m a n c e
public typealias DifferenceIdentifier = String
public var differenceIdentifier : String {
switch self {
case . developerMode : return " developerMode "
case . defaultLogLevel : return " defaultLogLevel "
case . advancedLogging : return " advancedLogging "
case . loggingCategory ( let categoryIdentifier ) : return " loggingCategory- \( categoryIdentifier ) "
case . serviceNetwork : return " serviceNetwork "
case . resetSnodeCache : return " resetSnodeCache "
case . updatedDisappearingMessages : return " updatedDisappearingMessages "
case . debugDisappearingMessageDurations : return " debugDisappearingMessageDurations "
case . updatedGroups : return " updatedGroups "
case . updatedGroupsDisableAutoApprove : return " updatedGroupsDisableAutoApprove "
case . updatedGroupsRemoveMessagesOnKick : return " updatedGroupsRemoveMessagesOnKick "
case . updatedGroupsAllowHistoricAccessOnInvite : return " updatedGroupsAllowHistoricAccessOnInvite "
case . updatedGroupsAllowDisplayPicture : return " updatedGroupsAllowDisplayPicture "
case . updatedGroupsAllowDescriptionEditing : return " updatedGroupsAllowDescriptionEditing "
case . updatedGroupsAllowPromotions : return " updatedGroupsAllowPromotions "
case . updatedGroupsAllowInviteById : return " updatedGroupsAllowInviteById "
case . exportDatabase : return " exportDatabase "
}
}
public func isContentEqual ( to source : TableItem ) -> Bool {
self . differenceIdentifier = = source . differenceIdentifier
}
public static var allCases : [ TableItem ] {
var result : [ TableItem ] = [ ]
switch TableItem . developerMode {
case . developerMode : result . append ( . developerMode ) ; fallthrough
case . defaultLogLevel : result . append ( . defaultLogLevel ) ; fallthrough
case . advancedLogging : result . append ( . advancedLogging ) ; fallthrough
case . loggingCategory : result . append ( . loggingCategory ( " " ) ) ; fallthrough
case . serviceNetwork : result . append ( . serviceNetwork ) ; fallthrough
case . resetSnodeCache : result . append ( . resetSnodeCache ) ; fallthrough
case . updatedDisappearingMessages : result . append ( . updatedDisappearingMessages ) ; fallthrough
case . debugDisappearingMessageDurations : result . append ( . debugDisappearingMessageDurations ) ; fallthrough
case . updatedGroups : result . append ( . updatedGroups ) ; fallthrough
case . updatedGroupsDisableAutoApprove : result . append ( . updatedGroupsDisableAutoApprove ) ; fallthrough
case . updatedGroupsRemoveMessagesOnKick : result . append ( . updatedGroupsRemoveMessagesOnKick ) ; fallthrough
case . updatedGroupsAllowHistoricAccessOnInvite :
result . append ( . updatedGroupsAllowHistoricAccessOnInvite ) ; fallthrough
case . updatedGroupsAllowDisplayPicture : result . append ( . updatedGroupsAllowDisplayPicture ) ; fallthrough
case . updatedGroupsAllowDescriptionEditing : result . append ( . updatedGroupsAllowDescriptionEditing ) ; fallthrough
case . updatedGroupsAllowPromotions : result . append ( . updatedGroupsAllowPromotions ) ; fallthrough
case . updatedGroupsAllowInviteById : result . append ( . updatedGroupsAllowInviteById ) ; fallthrough
case . exportDatabase : result . append ( . exportDatabase )
}
return result
}
}
// MARK: - C o n t e n t
@ -78,6 +149,10 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
private struct State : Equatable {
let developerMode : Bool
let defaultLogLevel : Log . Level
let advancedLogging : Bool
let loggingCategories : [ Log . Category : Log . Level ]
let serviceNetwork : ServiceNetwork
let debugDisappearingMessageDurations : Bool
@ -96,12 +171,19 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
let title : String = " Developer Settings "
lazy var observation : TargetObservation = ObservationBuilder
. refreshableData ( self ) { [ dependencies ] ( ) -> State in
. refreshableData ( self ) { [ weak self , dependencies ] ( ) -> State in
State (
developerMode : dependencies [ singleton : . storage , key : . developerModeEnabled ] ,
defaultLogLevel : dependencies [ feature : . logLevel ( cat : . default ) ] ,
advancedLogging : ( self ? . showAdvancedLogging = = true ) ,
loggingCategories : dependencies [ feature : . allLogLevels ] . currentValues ( using : dependencies ) ,
serviceNetwork : dependencies [ feature : . serviceNetwork ] ,
debugDisappearingMessageDurations : dependencies [ feature : . debugDisappearingMessageDurations ] ,
updatedDisappearingMessages : dependencies [ feature : . updatedDisappearingMessages ] ,
updatedGroups : dependencies [ feature : . updatedGroups ] ,
updatedGroupsDisableAutoApprove : dependencies [ feature : . updatedGroupsDisableAutoApprove ] ,
updatedGroupsRemoveMessagesOnKick : dependencies [ feature : . updatedGroupsRemoveMessagesOnKick ] ,
@ -141,6 +223,77 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
)
]
) ,
SectionModel (
model : . logging ,
elements : [
SessionCell . Info (
id : . defaultLogLevel ,
title : " Default Log Level " ,
subtitle : " " "
Sets the default log level
All logging categories which don ' t have a custom level set below will use this value
" " " ,
trailingAccessory : . dropDown { current . defaultLogLevel . title } ,
onTap : { [ weak self , dependencies ] in
self ? . transitionToScreen (
SessionTableViewController (
viewModel : SessionListViewModel < Log . Level > (
title : " Default Log Level " ,
options : Log . Level . allCases . filter { $0 != . default } ,
behaviour : . autoDismiss (
initialSelection : current . defaultLogLevel ,
onOptionSelected : self ? . updateDefaulLogLevel
) ,
using : dependencies
)
)
)
}
) ,
SessionCell . Info (
id : . advancedLogging ,
title : " Advanced Logging " ,
subtitle : " Show per-category log levels " ,
trailingAccessory : . toggle (
current . advancedLogging ,
oldValue : previous ? . advancedLogging
) ,
onTap : { [ weak self ] in
self ? . setAdvancedLoggingVisibility ( to : ! current . advancedLogging )
}
)
] . appending (
contentsOf : ! current . advancedLogging ? nil : current . loggingCategories
. sorted ( by : { lhs , rhs in lhs . key . rawValue < rhs . key . rawValue } )
. map { category , level in
SessionCell . Info (
id : . loggingCategory ( category . rawValue ) ,
title : category . rawValue ,
subtitle : " Sets the log level for the \( category . rawValue ) category " ,
trailingAccessory : . dropDown { level . title } ,
onTap : { [ weak self , dependencies ] in
self ? . transitionToScreen (
SessionTableViewController (
viewModel : SessionListViewModel < Log . Level > (
title : " \( category . rawValue ) Log Level " ,
options : [ Log . Level . default ] // M o v e ' d e f a u l t ' t o t h e t o p
. appending ( contentsOf : Log . Level . allCases . filter { $0 != . default } ) ,
behaviour : . autoDismiss (
initialSelection : level ,
onOptionSelected : { updatedLevel in
self ? . updateLogLevel ( of : category , to : updatedLevel )
}
) ,
using : dependencies
)
)
)
}
)
}
)
) ,
SectionModel (
model : . network ,
elements : [
@ -405,9 +558,13 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
// / t h e n w e w i l l g e t a c o m p i l e e r r o r i f i t d o e s n ' t g e t r e s e t t i n g i n s t r u c t i o n s a d d e d )
TableItem . allCases . forEach { item in
switch item {
case . developerMode : break // N o t a f e a t u r e
case . resetSnodeCache : break // N o t a f e a t u r e
case . exportDatabase : break // N o t a f e a t u r e
case . developerMode : break // N o t a f e a t u r e
case . resetSnodeCache : break // N o t a f e a t u r e
case . exportDatabase : break // N o t a f e a t u r e
case . advancedLogging : break // N o t a f e a t u r e
case . defaultLogLevel : updateDefaulLogLevel ( to : nil )
case . loggingCategory : resetLoggingCategories ( )
case . serviceNetwork : updateServiceNetwork ( to : nil )
@ -436,6 +593,31 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
self . dismissScreen ( type : . pop )
}
private func updateDefaulLogLevel ( to updatedDefaultLogLevel : Log . Level ? ) {
dependencies . set ( feature : . logLevel ( cat : . default ) , to : updatedDefaultLogLevel )
forceRefresh ( type : . databaseQuery )
}
private func setAdvancedLoggingVisibility ( to value : Bool ) {
self . showAdvancedLogging = value
forceRefresh ( type : . databaseQuery )
}
private func updateLogLevel ( of category : Log . Category , to level : Log . Level ) {
switch ( level , category . defaultLevel ) {
case ( . default , category . defaultLevel ) : dependencies . reset ( feature : . logLevel ( cat : category ) )
default : dependencies . set ( feature : . logLevel ( cat : category ) , to : level )
}
forceRefresh ( type : . databaseQuery )
}
private func resetLoggingCategories ( ) {
dependencies [ feature : . allLogLevels ] . currentValues ( using : dependencies ) . forEach { category , _ in
dependencies . reset ( feature : . logLevel ( cat : category ) )
}
forceRefresh ( type : . databaseQuery )
}
private func updateServiceNetwork ( to updatedNetwork : ServiceNetwork ? ) {
struct IdentityData {
let ed25519KeyPair : KeyPair
@ -471,19 +653,21 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
} )
else { return }
SN Log( " [DevSettings] Swapping to \( String ( describing : updatedNetwork ) ) , clearing data " )
Log. info ( " [DevSettings] Swapping to \( String ( describing : updatedNetwork ) ) , clearing data " )
// / S t o p a l l p o l l e r s
dependencies [ singleton : . currentUserPoller ] . stop ( )
dependencies . remove ( cache : . groupPollers )
// / / / C a n c e l a n d r e m o v e a l l c u r r e n t n e t w o r k r e q u e s t s
// d e p e n d e n c i e s . m u t a t e ( c a c h e : . n e t w o r k ) { n e t w o r k C a c h e i n
// n e t w o r k C a c h e . c u r r e n t R e q u e s t s . f o r E a c h { _ , v a l u e i n v a l u e . c a n c e l ( ) }
// n e t w o r k C a c h e . c u r r e n t R e q u e s t s = [ : ]
// }
// / R e s e t t h e n e t w o r k
dependencies . mutate ( cache : . libSessionNetwork ) {
$0 . setPaths ( paths : [ ] )
$0 . setNetworkStatus ( status : . unknown )
}
dependencies . remove ( cache : . libSessionNetwork )
// / U n s u b s c r i b e f r o m p u s h n o t i f i c a t i o n s ( d o t h i s a f t e r c a n c e l l i n g p e n d i n g n e t w o r k r e q u e s t s a s w e d o n ' t w a n t t h e s e t o b e c a n c e l l e d )
// / U n s u b s c r i b e f r o m p u s h n o t i f i c a t i o n s ( d o t h i s a f t e r r e s e t t i n g t h e n e t w o r k a s t h e y a r e s e r v e r r e q u e s t s s o a r e n ' t d e p e n d a n t o n a s e r v i c e
// / l a y e r a n d w e d o n ' t w a n t t h e s e t o b e c a n c e l l e d )
if let existingToken : String = dependencies [ singleton : . storage , key : . lastRecordedPushToken ] {
PushNotificationAPI
. unsubscribeAll ( token : Data ( hex : existingToken ) , using : dependencies )
@ -491,7 +675,7 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
}
// / C l e a r t h e s n o d e A P I c a c h e s
dependencies . remove ( cache : . snodeAPI ) // TODO: T e s t t h i s w o r k s
dependencies . remove ( cache : . snodeAPI )
// / R e m o v e a n y n e t w o r k - s p e c i f i c d a t a
dependencies [ singleton : . storage ] . write { [ dependencies ] db in
@ -514,14 +698,17 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
_ = try ConfigDump . deleteAll ( db )
}
SNLog ( " [DevSettings] Reloading state for \( String ( describing : updatedNetwork ) ) " )
// / R e l o a d t h e l i b S e s s i o n s t a t e
// / R e m o v e t h e l i b S e s s i o n s t a t e
dependencies . remove ( cache : . libSession )
Log . info ( " [DevSettings] Reloading state for \( String ( describing : updatedNetwork ) ) " )
// / U p d a t e t o t h e n e w ` S e r v i c e N e t w o r k `
dependencies . set ( feature : . serviceNetwork , to : updatedNetwork )
// / S t a r t t h e n e w n e t w o r k c a c h e
dependencies . warmCache ( cache : . libSessionNetwork )
// / R u n t h e o n b o a r d i n g p r o c e s s a s i f w e a r e r e c o v e r i n g a n a c c o u n t ( w i l l s e t u p t h e d e v i c e i n i t ' s p r o p e r s t a t e )
Onboarding . Cache (
ed25519KeyPair : identityData . ed25519KeyPair ,
@ -538,7 +725,7 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
// / R e - s y n c t h e p u s h t o k e n s ( i f t h e r e a r e a n y )
SyncPushTokensJob . run ( uploadOnlyIfStale : false , using : dependencies )
SN Log( " [DevSettings] Completed swap to \( String ( describing : updatedNetwork ) ) " )
Log. info ( " [DevSettings] Completed swap to \( String ( describing : updatedNetwork ) ) " )
}
forceRefresh ( type : . databaseQuery )
@ -564,7 +751,8 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
// / C l e a r t h e s n o d e A P I c a c h e
dependencies . remove ( cache : . snodeAPI )
// / C l e a r t h e s n o d e c a c h e
dependencies . mutate ( cache : . libSessionNetwork ) { $0 . clearSnodeCache ( ) }
}
)
) ,
@ -706,3 +894,4 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
// MARK: - L i s t a b l e C o n f o r m a n c e
extension ServiceNetwork : Listable { }
extension Log . Level : Listable { }