2021-03-16 19:54:48 +00:00
import ' dart:collection ' ;
2021-03-09 01:23:37 +00:00
import ' dart:ui ' ;
import ' dart:core ' ;
import ' package:flutter/material.dart ' ;
import ' package:package_info_plus/package_info_plus.dart ' ;
2021-03-10 17:40:14 +00:00
import ' opaque.dart ' ;
2021-03-24 23:35:24 +00:00
const TapirGroupsExperiment = " tapir-groups-experiment " ;
2021-03-16 19:54:48 +00:00
/// Settings govern the *Globally* relevant settings like Locale, Theme and Experiments.
/// We also provide access to the version information here as it is also accessed from the
/// Settings Pane.
2021-03-09 01:23:37 +00:00
class Settings extends ChangeNotifier {
Locale locale ;
2021-05-25 00:11:39 +00:00
late PackageInfo packageInfo ;
2021-03-10 17:40:14 +00:00
OpaqueThemeType theme ;
2021-06-04 18:13:52 +00:00
// explicitly set experiments to false until told otherwise...
bool experimentsEnabled = false ;
2021-03-16 19:54:48 +00:00
HashMap < String , bool > experiments = HashMap . identity ( ) ;
2021-03-10 17:40:14 +00:00
2021-05-25 00:11:39 +00:00
late bool blockUnknownConnections ;
2021-04-06 20:33:44 +00:00
2021-03-16 19:54:48 +00:00
/// Set the dark theme.
2021-03-10 17:40:14 +00:00
void setDark ( ) {
theme = Opaque . dark ;
notifyListeners ( ) ;
}
2021-03-16 19:54:48 +00:00
/// Set the Light theme.
2021-03-10 17:40:14 +00:00
void setLight ( ) {
theme = Opaque . light ;
notifyListeners ( ) ;
}
2021-03-16 19:54:48 +00:00
/// Get access to the current theme.
2021-03-10 17:40:14 +00:00
OpaqueThemeType current ( ) {
return theme ;
}
2021-06-04 18:13:52 +00:00
/// isExperimentEnabled can be used to safely check whether a particular
/// experiment is enabled
bool isExperimentEnabled ( String experiment ) {
if ( this . experimentsEnabled ) {
if ( this . experiments . containsKey ( experiment ) ) {
// We now know it cannot be null...
return this . experiments [ experiment ] ! = = true ;
}
}
return false ;
}
2021-03-16 19:54:48 +00:00
/// Called by the event bus. When new settings are loaded from a file the JSON will
/// be sent to the function and new settings will be instantiated based on the contents.
2021-03-10 17:40:14 +00:00
handleUpdate ( dynamic settings ) {
2021-03-16 19:54:48 +00:00
// Set Theme and notify listeners
2021-03-10 17:40:14 +00:00
if ( settings [ " Theme " ] = = " light " ) {
this . setLight ( ) ;
} else {
this . setDark ( ) ;
}
2021-03-16 19:54:48 +00:00
// Set Locale and notify listeners
switchLocale ( Locale ( settings [ " Locale " ] ) ) ;
2021-04-06 20:33:44 +00:00
// Decide whether to enable Experiments
blockUnknownConnections = settings [ " BlockUnknownConnections " ] ;
2021-03-16 19:54:48 +00:00
// Decide whether to enable Experiments
experimentsEnabled = settings [ " ExperimentsEnabled " ] ;
// Set the internal experiments map. Casting from the Map<dynamic, dynamic> that we get from JSON
experiments = new HashMap < String , bool > . from ( settings [ " Experiments " ] ) ;
// Push the experimental settings to Consumers of Settings
2021-03-10 17:40:14 +00:00
notifyListeners ( ) ;
}
2021-03-16 19:54:48 +00:00
/// Initialize the Package Version information
2021-03-09 01:23:37 +00:00
initPackageInfo ( ) {
PackageInfo . fromPlatform ( ) . then ( ( PackageInfo newPackageInfo ) {
packageInfo = newPackageInfo ;
notifyListeners ( ) ;
} ) ;
}
2021-04-06 20:33:44 +00:00
/// Switch the Locale of the App
2021-03-09 01:23:37 +00:00
switchLocale ( Locale newLocale ) {
locale = newLocale ;
notifyListeners ( ) ;
}
2021-04-06 20:33:44 +00:00
/// Block Unknown Connections will autoblock connections if they authenticate with public key not in our contacts list.
/// This is one of the best tools we have to combat abuse, while it isn't ideal it does allow a user to curate their contacts
/// list without being bothered by spurious requests (either permanently, or as a short term measure).
/// Note: This is not an *appear offline* setting which would explicitly close the listen port, rather than simply auto disconnecting unknown attempts.
forbidUnknownConnections ( ) {
blockUnknownConnections = true ;
notifyListeners ( ) ;
}
/// Allow Unknown Connections will allow new contact requires from unknown public keys
/// See above for more information.
allowUnknownConnections ( ) {
blockUnknownConnections = false ;
notifyListeners ( ) ;
}
2021-03-16 19:54:48 +00:00
/// Turn Experiments On, this will also have the side effect of enabling any
/// Experiments that have been previously activated.
enableExperiments ( ) {
experimentsEnabled = true ;
notifyListeners ( ) ;
}
/// Turn Experiments Off. This will disable **all** active experiments.
/// Note: This will not set the preference for individual experiments, if experiments are enabled
/// any experiments that were active previously will become active again unless they are explicitly disabled.
disableExperiments ( ) {
experimentsEnabled = false ;
notifyListeners ( ) ;
}
/// Turn on a specific experiment.
enableExperiment ( String key ) {
experiments . update ( key , ( value ) = > true , ifAbsent: ( ) = > true ) ;
2021-05-27 20:28:31 +00:00
notifyListeners ( ) ;
2021-03-16 19:54:48 +00:00
}
/// Turn off a specific experiment
disableExperiment ( String key ) {
experiments . update ( key , ( value ) = > false , ifAbsent: ( ) = > false ) ;
2021-05-27 20:28:31 +00:00
notifyListeners ( ) ;
2021-03-16 19:54:48 +00:00
}
/// Construct a default settings object.
2021-03-10 17:40:14 +00:00
Settings ( this . locale , this . theme ) ;
2021-03-16 19:54:48 +00:00
/// Convert this Settings object to a JSON representation for serialization on the
/// event bus.
2021-03-10 17:40:14 +00:00
dynamic asJson ( ) {
var themeString = " light " ;
if ( theme = = Opaque . dark ) {
themeString = " dark " ;
}
return {
" Locale " : this . locale . languageCode ,
" Theme " : themeString ,
" PreviousPid " : - 1 ,
2021-04-06 20:33:44 +00:00
" BlockUnknownConnections " : blockUnknownConnections ,
2021-03-16 19:54:48 +00:00
" ExperimentsEnabled " : this . experimentsEnabled ,
" Experiments " : experiments ,
2021-03-10 17:40:14 +00:00
" StateRootPane " : 0 ,
" FirstTime " : false
} ;
}
}