From d142c10fef7532c76a310862edaeca87e7c4e813 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Thu, 4 Jan 2024 01:53:10 -0800 Subject: [PATCH] settings into pane --- lib/views/globalsettingsview.dart | 1398 ++++++++++++++++++----------- 1 file changed, 860 insertions(+), 538 deletions(-) diff --git a/lib/views/globalsettingsview.dart b/lib/views/globalsettingsview.dart index 69829d6f..f32f7cc4 100644 --- a/lib/views/globalsettingsview.dart +++ b/lib/views/globalsettingsview.dart @@ -24,7 +24,8 @@ class GlobalSettingsView extends StatefulWidget { class _GlobalSettingsViewState extends State { static const androidSettingsChannel = const MethodChannel('androidSettings'); - static const androidSettingsChangeChannel = const MethodChannel('androidSettingsChanged'); + static const androidSettingsChangeChannel = + const MethodChannel('androidSettingsChanged'); bool powerExempt = false; ScrollController settingsListScrollController = ScrollController(); @@ -62,7 +63,8 @@ class _GlobalSettingsViewState extends State { //* Android Only Requests Future isBatteryExempt() async { - return await androidSettingsChannel.invokeMethod('isBatteryExempt', {}) ?? false; + return await androidSettingsChannel.invokeMethod('isBatteryExempt', {}) ?? + false; } Future requestBatteryExemption() async { @@ -74,571 +76,885 @@ class _GlobalSettingsViewState extends State { @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(AppLocalizations.of(context)!.cwtchSettingsTitle), - ), - body: _buildSettingsList(), - ); + return DefaultTabController( + length: 4, + child: Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.cwtchSettingsTitle), + bottom: TabBar( + tabs: [ + Tab( + icon: Icon(Icons.palette), + text: AppLocalizations.of(context)! + .settingsGroupAppearance), + Tab( + icon: Icon(Icons.settings), + text: + AppLocalizations.of(context)!.settingGroupBehaviour), + Tab( + icon: Icon(CwtchIcons.enable_experiments), + text: AppLocalizations.of(context)! + .settingsGroupExperiments), + Tab(icon: Icon(Icons.info), text: "About"), + ], + )), + body: _buildSettingsList(), + )); } Widget _buildSettingsList() { return Consumer(builder: (ccontext, settings, child) { - return LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) { + return LayoutBuilder( + builder: (BuildContext context, BoxConstraints viewportConstraints) { var appIcon = Icon(Icons.info, color: settings.current().mainTextColor); - return Scrollbar( - key: Key("SettingsView"), - trackVisibility: true, - controller: settingsListScrollController, - child: SingleChildScrollView( - clipBehavior: Clip.antiAlias, - controller: settingsListScrollController, - padding: EdgeInsets.all(20), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Column(children: [ - Row(mainAxisAlignment: MainAxisAlignment.center, children: [Text(AppLocalizations.of(context)!.settingsGroupAppearance, style: TextStyle(fontWeight: FontWeight.bold))]), - ListTile( - title: Text(AppLocalizations.of(context)!.settingLanguage), - leading: Icon(CwtchIcons.change_language, color: settings.current().mainTextColor), + return TabBarView(children: [ + // ***** Appearance + Scrollbar( + key: Key("SettingsView"), + trackVisibility: true, + controller: settingsListScrollController, + child: SingleChildScrollView( + clipBehavior: Clip.antiAlias, + controller: settingsListScrollController, + padding: EdgeInsets.symmetric(vertical: 0, horizontal: 20), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Column(children: [ + ListTile( + title: Text( + AppLocalizations.of(context)!.settingLanguage), + leading: Icon(CwtchIcons.change_language, + color: settings.current().mainTextColor), + trailing: Container( + width: MediaQuery.of(context).size.width / 4, + child: DropdownButton( + key: Key("languagelist"), + isExpanded: true, + value: Provider.of(context) + .locale + .toString(), + onChanged: (String? newValue) { + setState(() { + EnvironmentConfig.debugLog( + "setting language: $newValue"); + settings.switchLocaleByCode(newValue!); + saveSettings(context); + }); + }, + items: AppLocalizations.supportedLocales + .map>( + (Locale value) { + return DropdownMenuItem( + value: value.toString(), + child: Text( + key: Key("dropdownLanguage" + + value.languageCode), + getLanguageFull( + context, + value.languageCode, + value.countryCode), + style: settings.scaleFonts( + defaultDropDownMenuItemTextStyle), + overflow: TextOverflow.ellipsis, + ), + ); + }).toList()))), + SwitchListTile( + title: + Text(AppLocalizations.of(context)!.settingTheme), + value: settings.current().mode == mode_light, + onChanged: (bool value) { + if (value) { + settings.setTheme( + settings.theme.theme, mode_light); + } else { + settings.setTheme( + settings.theme.theme, mode_dark); + } + + // Save Settings... + saveSettings(context); + }, + activeTrackColor: settings.theme.defaultButtonColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(CwtchIcons.change_theme, + color: settings.current().mainTextColor), + ), + ListTile( + title: Text( + AppLocalizations.of(context)!.themeColorLabel), trailing: Container( width: MediaQuery.of(context).size.width / 4, - child: DropdownButton( - key: Key("languagelist"), + child: DropdownButton( + key: Key("DropdownTheme"), isExpanded: true, - value: Provider.of(context).locale.toString(), + value: Provider.of(context) + .theme + .theme, onChanged: (String? newValue) { setState(() { - EnvironmentConfig.debugLog("setting language: $newValue"); - settings.switchLocaleByCode(newValue!); + settings.setTheme( + newValue!, settings.theme.mode); saveSettings(context); }); }, - items: AppLocalizations.supportedLocales.map>((Locale value) { + items: themes.keys + .map>( + (String themeId) { return DropdownMenuItem( - value: value.toString(), + value: themeId, child: Text( - key: Key("dropdownLanguage" + value.languageCode), - getLanguageFull(context, value.languageCode, value.countryCode), - style: settings.scaleFonts(defaultDropDownMenuItemTextStyle), - overflow: TextOverflow.ellipsis, - ), + getThemeName(context, themeId), + style: settings.scaleFonts( + defaultDropDownMenuItemTextStyle)), //"ddi_$themeId", key: Key("ddi_$themeId")), ); - }).toList()))), - SwitchListTile( - title: Text(AppLocalizations.of(context)!.settingTheme), - value: settings.current().mode == mode_light, - onChanged: (bool value) { - if (value) { - settings.setTheme(settings.theme.theme, mode_light); - } else { - settings.setTheme(settings.theme.theme, mode_dark); - } - - // Save Settings... - saveSettings(context); - }, - activeTrackColor: settings.theme.defaultButtonColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(CwtchIcons.change_theme, color: settings.current().mainTextColor), - ), - ListTile( - title: Text(AppLocalizations.of(context)!.themeColorLabel), - trailing: Container( - width: MediaQuery.of(context).size.width / 4, - child: DropdownButton( - key: Key("DropdownTheme"), - isExpanded: true, - value: Provider.of(context).theme.theme, - onChanged: (String? newValue) { - setState(() { - settings.setTheme(newValue!, settings.theme.mode); + }).toList())), + leading: Icon(Icons.palette, + color: settings.current().mainTextColor), + ), + ListTile( + title: Text(AppLocalizations.of(context)! + .settingUIColumnPortrait), + leading: Icon(Icons.table_chart, + color: settings.current().mainTextColor), + trailing: Container( + width: MediaQuery.of(context).size.width / 4, + child: DropdownButton( + isExpanded: true, + value: settings.uiColumnModePortrait + .toString(), + onChanged: (String? newValue) { + settings.uiColumnModePortrait = + Settings.uiColumnModeFromString( + newValue!); + saveSettings(context); + }, + items: Settings.uiColumnModeOptions(false) + .map>( + (DualpaneMode value) { + return DropdownMenuItem( + value: value.toString(), + child: Text( + Settings.uiColumnModeToString( + value, context), + style: settings.scaleFonts( + defaultDropDownMenuItemTextStyle)), + ); + }).toList()))), + ListTile( + title: Text( + AppLocalizations.of(context)! + .settingUIColumnLandscape, + textWidthBasis: TextWidthBasis.longestLine, + softWrap: true, + ), + leading: Icon(Icons.stay_primary_landscape, + color: settings.current().mainTextColor), + trailing: Container( + width: MediaQuery.of(context).size.width / 4, + child: Container( + width: + MediaQuery.of(context).size.width / 4, + child: DropdownButton( + isExpanded: true, + value: settings.uiColumnModeLandscape + .toString(), + onChanged: (String? newValue) { + settings.uiColumnModeLandscape = + Settings.uiColumnModeFromString( + newValue!); + saveSettings(context); + }, + items: + Settings.uiColumnModeOptions(true) + .map>( + (DualpaneMode value) { + return DropdownMenuItem( + value: value.toString(), + child: Text( + Settings.uiColumnModeToString( + value, context), + overflow: TextOverflow.ellipsis, + style: settings.scaleFonts( + defaultDropDownMenuItemTextStyle)), + ); + }).toList())))), + ListTile( + title: Text( + AppLocalizations.of(context)!.defaultScalingText), + subtitle: Text(AppLocalizations.of(context)! + .fontScalingDescription), + trailing: Container( + width: MediaQuery.of(context).size.width / 4, + child: Slider( + onChanged: (double value) { + settings.fontScaling = value; + // Save Settings... saveSettings(context); - }); - }, - items: themes.keys.map>((String themeId) { - return DropdownMenuItem( - value: themeId, - child: Text(getThemeName(context, themeId), style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)), //"ddi_$themeId", key: Key("ddi_$themeId")), - ); - }).toList())), - leading: Icon(Icons.palette, color: settings.current().mainTextColor), + EnvironmentConfig.debugLog( + "Font Scaling: $value"); + }, + min: 0.5, + divisions: 12, + max: 2.0, + label: '${settings.fontScaling * 100}%', + activeColor: + settings.current().defaultButtonColor, + thumbColor: settings.current().mainTextColor, + overlayColor: MaterialStateProperty.all( + settings.current().mainTextColor), + inactiveColor: + settings.theme.defaultButtonDisabledColor, + value: settings.fontScaling)), + leading: Icon(Icons.format_size, + color: settings.current().mainTextColor), + ), + SwitchListTile( + title: Text( + AppLocalizations.of(context)!.streamerModeLabel), + subtitle: Text(AppLocalizations.of(context)! + .descriptionStreamerMode), + value: settings.streamerMode, + onChanged: (bool value) { + settings.setStreamerMode(value); + // Save Settings... + saveSettings(context); + }, + activeTrackColor: settings.theme.defaultButtonColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(CwtchIcons.streamer_bunnymask, + color: settings.current().mainTextColor), + ), + SwitchListTile( + title: Text(AppLocalizations.of(context)! + .formattingExperiment), + subtitle: Text(AppLocalizations.of(context)! + .messageFormattingDescription), + value: settings + .isExperimentEnabled(FormattingExperiment), + onChanged: (bool value) { + if (value) { + settings.enableExperiment(FormattingExperiment); + } else { + settings.disableExperiment(FormattingExperiment); + } + saveSettings(context); + }, + activeTrackColor: + settings.theme.defaultButtonActiveColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(Icons.text_fields, + color: settings.current().mainTextColor), + ), + ])))), + + // **** Behaviour + Scrollbar( + key: Key("SettingsView"), + trackVisibility: true, + controller: settingsListScrollController, + child: SingleChildScrollView( + clipBehavior: Clip.antiAlias, + controller: settingsListScrollController, + padding: EdgeInsets.symmetric(vertical: 0, horizontal: 20), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, ), - ListTile( - title: Text(AppLocalizations.of(context)!.settingUIColumnPortrait), - leading: Icon(Icons.table_chart, color: settings.current().mainTextColor), + child: Column(children: [ + Visibility( + visible: Platform.isAndroid, + child: SwitchListTile( + title: Text(AppLocalizations.of(context)! + .settingAndroidPowerExemption), + subtitle: Text(AppLocalizations.of(context)! + .settingAndroidPowerExemptionDescription), + value: powerExempt, + onChanged: (bool value) { + if (value) { + requestBatteryExemption(); + } else { + // We can't ask for it to be turned off, show an informational popup + showBatteryDialog(context); + } + }, + activeTrackColor: settings.theme.defaultButtonColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(Icons.power, + color: settings.current().mainTextColor), + ), + ), + ListTile( + title: Text(AppLocalizations.of(context)! + .notificationPolicySettingLabel), + subtitle: Text(AppLocalizations.of(context)! + .notificationPolicySettingDescription), trailing: Container( width: MediaQuery.of(context).size.width / 4, child: DropdownButton( isExpanded: true, - value: settings.uiColumnModePortrait.toString(), - onChanged: (String? newValue) { - settings.uiColumnModePortrait = Settings.uiColumnModeFromString(newValue!); + value: settings.notificationPolicy, + onChanged: (NotificationPolicy? newValue) { + settings.notificationPolicy = newValue!; saveSettings(context); }, - items: Settings.uiColumnModeOptions(false).map>((DualpaneMode value) { - return DropdownMenuItem( - value: value.toString(), - child: Text(Settings.uiColumnModeToString(value, context), style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)), + items: NotificationPolicy.values.map< + DropdownMenuItem>( + (NotificationPolicy value) { + return DropdownMenuItem( + value: value, + child: Text( + Settings.notificationPolicyToString( + value, context), + overflow: TextOverflow.ellipsis, + style: settings.scaleFonts( + defaultDropDownMenuItemTextStyle)), ); - }).toList()))), - ListTile( - title: Text( - AppLocalizations.of(context)!.settingUIColumnLandscape, - textWidthBasis: TextWidthBasis.longestLine, - softWrap: true, - ), - leading: Icon(Icons.stay_primary_landscape, color: settings.current().mainTextColor), + }).toList())), + leading: Icon(CwtchIcons.chat_bubble_empty_24px, + color: settings.current().mainTextColor), + ), + ListTile( + title: Text(AppLocalizations.of(context)! + .notificationContentSettingLabel), + subtitle: Text(AppLocalizations.of(context)! + .notificationContentSettingDescription), trailing: Container( width: MediaQuery.of(context).size.width / 4, - child: Container( - width: MediaQuery.of(context).size.width / 4, - child: DropdownButton( - isExpanded: true, - value: settings.uiColumnModeLandscape.toString(), - onChanged: (String? newValue) { - settings.uiColumnModeLandscape = Settings.uiColumnModeFromString(newValue!); - saveSettings(context); - }, - items: Settings.uiColumnModeOptions(true).map>((DualpaneMode value) { - return DropdownMenuItem( - value: value.toString(), - child: Text(Settings.uiColumnModeToString(value, context), overflow: TextOverflow.ellipsis, style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)), - ); - }).toList())))), - ListTile( - title: Text(AppLocalizations.of(context)!.defaultScalingText), - subtitle: Text(AppLocalizations.of(context)!.fontScalingDescription), - trailing: Container( - width: MediaQuery.of(context).size.width / 4, - child: Slider( - onChanged: (double value) { - settings.fontScaling = value; - // Save Settings... - saveSettings(context); - EnvironmentConfig.debugLog("Font Scaling: $value"); - }, - min: 0.5, - divisions: 12, - max: 2.0, - label: '${settings.fontScaling * 100}%', - activeColor: settings.current().defaultButtonColor, - thumbColor: settings.current().mainTextColor, - overlayColor: MaterialStateProperty.all(settings.current().mainTextColor), - inactiveColor: settings.theme.defaultButtonDisabledColor, - value: settings.fontScaling)), - leading: Icon(Icons.format_size, color: settings.current().mainTextColor), - ), - SwitchListTile( - title: Text(AppLocalizations.of(context)!.streamerModeLabel), - subtitle: Text(AppLocalizations.of(context)!.descriptionStreamerMode), - value: settings.streamerMode, - onChanged: (bool value) { - settings.setStreamerMode(value); - // Save Settings... - saveSettings(context); - }, - activeTrackColor: settings.theme.defaultButtonColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(CwtchIcons.streamer_bunnymask, color: settings.current().mainTextColor), - ), - SwitchListTile( - title: Text(AppLocalizations.of(context)!.formattingExperiment), - subtitle: Text(AppLocalizations.of(context)!.messageFormattingDescription), - value: settings.isExperimentEnabled(FormattingExperiment), - onChanged: (bool value) { - if (value) { - settings.enableExperiment(FormattingExperiment); - } else { - settings.disableExperiment(FormattingExperiment); - } - saveSettings(context); - }, - activeTrackColor: settings.theme.defaultButtonActiveColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(Icons.text_fields, color: settings.current().mainTextColor), - ), - SizedBox( - height: 40, - ), - Row(mainAxisAlignment: MainAxisAlignment.center, children: [Text(AppLocalizations.of(context)!.settingGroupBehaviour, style: TextStyle(fontWeight: FontWeight.bold))]), - Visibility( - visible: Platform.isAndroid, - child: SwitchListTile( - title: Text(AppLocalizations.of(context)!.settingAndroidPowerExemption), - subtitle: Text(AppLocalizations.of(context)!.settingAndroidPowerExemptionDescription), - value: powerExempt, - onChanged: (bool value) { - if (value) { - requestBatteryExemption(); - } else { - // We can't ask for it to be turned off, show an informational popup - showBatteryDialog(context); - } - }, - activeTrackColor: settings.theme.defaultButtonColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(Icons.power, color: settings.current().mainTextColor), - ), - ), - ListTile( - title: Text(AppLocalizations.of(context)!.notificationPolicySettingLabel), - subtitle: Text(AppLocalizations.of(context)!.notificationPolicySettingDescription), - trailing: Container( - width: MediaQuery.of(context).size.width / 4, - child: DropdownButton( - isExpanded: true, - value: settings.notificationPolicy, - onChanged: (NotificationPolicy? newValue) { - settings.notificationPolicy = newValue!; - saveSettings(context); - }, - items: NotificationPolicy.values.map>((NotificationPolicy value) { - return DropdownMenuItem( - value: value, - child: Text(Settings.notificationPolicyToString(value, context), overflow: TextOverflow.ellipsis, style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)), - ); - }).toList())), - leading: Icon(CwtchIcons.chat_bubble_empty_24px, color: settings.current().mainTextColor), - ), - ListTile( - title: Text(AppLocalizations.of(context)!.notificationContentSettingLabel), - subtitle: Text(AppLocalizations.of(context)!.notificationContentSettingDescription), - trailing: Container( - width: MediaQuery.of(context).size.width / 4, - child: DropdownButton( - isExpanded: true, - value: settings.notificationContent, - onChanged: (NotificationContent? newValue) { - settings.notificationContent = newValue!; - saveSettings(context); - }, - items: NotificationContent.values.map>((NotificationContent value) { - return DropdownMenuItem( - value: value, - child: Text(Settings.notificationContentToString(value, context), overflow: TextOverflow.ellipsis, style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)), - ); - }).toList())), - leading: Icon(CwtchIcons.chat_bubble_empty_24px, color: settings.current().mainTextColor), - ), - SwitchListTile( - title: Text(AppLocalizations.of(context)!.blockUnknownLabel), - subtitle: Text(AppLocalizations.of(context)!.descriptionBlockUnknownConnections), - value: settings.blockUnknownConnections, - onChanged: (bool value) { - if (value) { - settings.forbidUnknownConnections(); - } else { - settings.allowUnknownConnections(); - } - - // Save Settings... - saveSettings(context); - }, - activeTrackColor: settings.theme.defaultButtonColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(CwtchIcons.block_unknown, color: settings.current().mainTextColor), - ), - SwitchListTile( - title: Text(AppLocalizations.of(context)!.defaultPreserveHistorySetting), - subtitle: Text(AppLocalizations.of(context)!.preserveHistorySettingDescription), - value: settings.preserveHistoryByDefault, - onChanged: (bool value) { - if (value) { - settings.setPreserveHistoryDefault(); - } else { - settings.setDeleteHistoryDefault(); - } - - // Save Settings... - saveSettings(context); - }, - activeTrackColor: settings.theme.defaultButtonColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(CwtchIcons.peer_history, color: settings.current().mainTextColor), - ), - SizedBox( - height: 40, - ), - Row(mainAxisAlignment: MainAxisAlignment.center, children: [Text(AppLocalizations.of(context)!.settingsGroupExperiments, style: TextStyle(fontWeight: FontWeight.bold))]), - SwitchListTile( - title: Text(AppLocalizations.of(context)!.experimentsEnabled), - subtitle: Text(AppLocalizations.of(context)!.descriptionExperiments), - value: settings.experimentsEnabled, - onChanged: (bool value) { - if (value) { - settings.enableExperiments(); - } else { - settings.disableExperiments(); - } - // Save Settings... - saveSettings(context); - }, - activeTrackColor: settings.theme.defaultButtonColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(CwtchIcons.enable_experiments, color: settings.current().mainTextColor), - ), - Visibility( - visible: settings.experimentsEnabled, - child: Column( - children: [ - SwitchListTile( - title: Text(AppLocalizations.of(context)!.enableGroups), - subtitle: Text(AppLocalizations.of(context)!.descriptionExperimentsGroups), - value: settings.isExperimentEnabled(TapirGroupsExperiment), - onChanged: (bool value) { - if (value) { - settings.enableExperiment(TapirGroupsExperiment); - } else { - settings.disableExperiment(TapirGroupsExperiment); - } - // Save Settings... - saveSettings(context); - }, - activeTrackColor: settings.theme.defaultButtonColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(CwtchIcons.enable_groups, color: settings.current().mainTextColor), - ), - Visibility( - visible: !Platform.isAndroid && !Platform.isIOS, - child: SwitchListTile( - title: Text(AppLocalizations.of(context)!.settingServers), - subtitle: Provider.of(context, listen: false).cwtch.IsServersCompiled() - ? Text(AppLocalizations.of(context)!.settingServersDescription) - : Text("This version of Cwtch has been compiled without support for the server hosting experiment."), - value: Provider.of(context, listen: false).cwtch.IsServersCompiled() && settings.isExperimentEnabled(ServerManagementExperiment), - onChanged: Provider.of(context, listen: false).cwtch.IsServersCompiled() - ? (bool value) { - Provider.of(context, listen: false).clear(); - if (value) { - settings.enableExperiment(ServerManagementExperiment); - } else { - settings.disableExperiment(ServerManagementExperiment); - } - // Save Settings... - saveSettings(context); - } - : null, - activeTrackColor: settings.theme.defaultButtonColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - inactiveThumbColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(CwtchIcons.dns_24px), - )), - SwitchListTile( - title: Text(AppLocalizations.of(context)!.settingFileSharing), - subtitle: Text(AppLocalizations.of(context)!.descriptionFileSharing), - value: settings.isExperimentEnabled(FileSharingExperiment), - onChanged: (bool value) { - if (value) { - if (checkDownloadDirectory(context, settings)) { - settings.enableExperiment(FileSharingExperiment); - } else { - settings.enableExperiment(FileSharingExperiment); - settings.disableExperiment(ImagePreviewsExperiment); - } - } else { - settings.disableExperiment(FileSharingExperiment); - settings.disableExperiment(ImagePreviewsExperiment); - } - saveSettings(context); - }, - activeTrackColor: settings.theme.defaultButtonColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(CwtchIcons.attached_file_3, color: settings.current().mainTextColor), - ), - Visibility( - visible: settings.isExperimentEnabled(FileSharingExperiment), - child: Column(children: [ - SwitchListTile( - title: Text(AppLocalizations.of(context)!.settingImagePreviews), - subtitle: Text(AppLocalizations.of(context)!.settingImagePreviewsDescription), - value: settings.isExperimentEnabled(ImagePreviewsExperiment), - onChanged: (bool value) { - if (value) { - if (checkDownloadDirectory(context, settings)) { - settings.enableExperiment(ImagePreviewsExperiment); - } else { - settings.disableExperiment(ImagePreviewsExperiment); - } - } else { - settings.disableExperiment(ImagePreviewsExperiment); - } - saveSettings(context); - }, - activeTrackColor: settings.theme.defaultButtonActiveColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(Icons.photo, color: settings.current().mainTextColor), - ), - Visibility( - visible: settings.isExperimentEnabled(ImagePreviewsExperiment) && !Platform.isAndroid, - child: CwtchFolderPicker( - testKey: Key("DownloadFolderPicker"), - label: AppLocalizations.of(context)!.settingDownloadFolder, - initialValue: settings.downloadPath, - textStyle: settings.scaleFonts(defaultDropDownMenuItemTextStyle), - description: AppLocalizations.of(context)!.fileSharingSettingsDownloadFolderDescription, - tooltip: AppLocalizations.of(context)!.fileSharingSettingsDownloadFolderTooltip, - onSave: (newVal) { - settings.downloadPath = newVal; - saveSettings(context); - }, - ), - ), - ]), - ), - SwitchListTile( - title: Text(AppLocalizations.of(context)!.blodeuweddExperimentEnable), - subtitle: Provider.of(context, listen: false).cwtch.IsBlodeuweddSupported() - ? Text(AppLocalizations.of(context)!.blodeuweddDescription) - : Text(AppLocalizations.of(context)!.blodeuweddNotSupported), - value: Provider.of(context, listen: false).cwtch.IsBlodeuweddSupported() && settings.isExperimentEnabled(BlodeuweddExperiment), - onChanged: Provider.of(context, listen: false).cwtch.IsBlodeuweddSupported() - ? (bool value) { - if (value) { - settings.enableExperiment(BlodeuweddExperiment); - } else { - settings.disableExperiment(BlodeuweddExperiment); - } - saveSettings(context); - } - : null, - activeTrackColor: settings.theme.defaultButtonColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - inactiveThumbColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(Icons.assistant, color: settings.current().mainTextColor), - ), - Visibility( - visible: Provider.of(context, listen: false).cwtch.IsBlodeuweddSupported() && settings.isExperimentEnabled(BlodeuweddExperiment), - child: CwtchFolderPicker( - testKey: Key("DownloadFolderPicker"), - label: AppLocalizations.of(context)!.settingDownloadFolder, - initialValue: settings.blodeuweddPath, - description: AppLocalizations.of(context)!.blodeuweddPath, - tooltip: AppLocalizations.of(context)!.blodeuweddPath, - onSave: (newVal) { - settings.blodeuweddPath = newVal; + child: DropdownButton( + isExpanded: true, + value: settings.notificationContent, + onChanged: (NotificationContent? newValue) { + settings.notificationContent = newValue!; saveSettings(context); }, - ), - ), - ], - )), - Visibility( - visible: settings.experimentsEnabled, - child: SwitchListTile( - title: Text(AppLocalizations.of(context)!.enableExperimentClickableLinks), - subtitle: Text(AppLocalizations.of(context)!.experimentClickableLinksDescription), - value: settings.isExperimentEnabled(ClickableLinksExperiment), - onChanged: (bool value) { - if (value) { - settings.enableExperiment(ClickableLinksExperiment); - } else { - settings.disableExperiment(ClickableLinksExperiment); - } - saveSettings(context); - }, - activeTrackColor: settings.theme.defaultButtonActiveColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(Icons.link, color: settings.current().mainTextColor), - )), - Visibility( - visible: settings.experimentsEnabled, - child: SwitchListTile( - title: Text(AppLocalizations.of(context)!.enableExperimentQRCode), - subtitle: Text(AppLocalizations.of(context)!.experimentQRCodeDescription), - value: settings.isExperimentEnabled(QRCodeExperiment), - onChanged: (bool value) { - if (value) { - settings.enableExperiment(QRCodeExperiment); - } else { - settings.disableExperiment(QRCodeExperiment); - } - saveSettings(context); - }, - activeTrackColor: settings.theme.defaultButtonActiveColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(Icons.qr_code, color: settings.current().mainTextColor), - )), - AboutListTile( - icon: appIcon, - applicationIcon: Padding(padding: EdgeInsets.all(5), child: Icon(CwtchIcons.cwtch_knott)), - applicationName: "Cwtch UI", - applicationLegalese: '\u{a9} 2021-2023 Open Privacy Research Society', - aboutBoxChildren: [ - Padding( - padding: EdgeInsets.fromLTRB(24.0 + 10.0 + (appIcon.size ?? 24.0), 16.0, 0.0, 0.0), - // About has 24 padding (ln 389) and there appears to be another 10 of padding in the widget - child: SelectableText(AppLocalizations.of(context)!.versionBuilddate.replaceAll("%1", EnvironmentConfig.BUILD_VER).replaceAll("%2", EnvironmentConfig.BUILD_DATE)), - ) - ]), - SwitchListTile( - // TODO: Translate, Remove, OR Hide Prior to Release - title: Text("Show Performance Overlay"), - subtitle: Text("Display an overlay graph of render time."), - value: settings.profileMode, - onChanged: (bool value) { - setState(() { - if (value) { - settings.profileMode = value; - } else { - settings.profileMode = value; - } - }); - }, - activeTrackColor: settings.theme.defaultButtonActiveColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(Icons.bar_chart, color: settings.current().mainTextColor), - ), - Visibility( - visible: EnvironmentConfig.BUILD_VER == dev_version && !Platform.isAndroid, - child: SwitchListTile( - title: Text("Show Semantic Debugger"), - subtitle: Text("Show Accessibility Debugging View"), - value: settings.useSemanticDebugger, - onChanged: (bool value) { - if (value) { - settings.useSemanticDebugger = value; - } else { - settings.useSemanticDebugger = value; - } - saveSettings(context); - }, - activeTrackColor: settings.theme.defaultButtonActiveColor, - inactiveTrackColor: settings.theme.defaultButtonDisabledColor, - secondary: Icon(Icons.settings_accessibility, color: settings.current().mainTextColor), - )), - Visibility( - visible: EnvironmentConfig.BUILD_VER == dev_version && !Platform.isAndroid, - child: FutureBuilder( - future: EnvironmentConfig.BUILD_VER != dev_version || Platform.isAndroid ? null : Provider.of(context).cwtch.GetDebugInfo(), - builder: (context, snapshot) { - if (snapshot.hasData) { - return Column( - children: [ - Text("libCwtch Debug Info: " + snapshot.data.toString()), - Text("Message Cache Size (Mb): " + (Provider.of(context).profs.cacheMemUsage() / (1024 * 1024)).toString()) - ], - ); - } else { - return Container(); - } - }, + items: NotificationContent.values.map< + DropdownMenuItem< + NotificationContent>>( + (NotificationContent value) { + return DropdownMenuItem< + NotificationContent>( + value: value, + child: Text( + Settings.notificationContentToString( + value, context), + overflow: TextOverflow.ellipsis, + style: settings.scaleFonts( + defaultDropDownMenuItemTextStyle)), + ); + }).toList())), + leading: Icon(CwtchIcons.chat_bubble_empty_24px, + color: settings.current().mainTextColor), ), + SwitchListTile( + title: Text( + AppLocalizations.of(context)!.blockUnknownLabel), + subtitle: Text(AppLocalizations.of(context)! + .descriptionBlockUnknownConnections), + value: settings.blockUnknownConnections, + onChanged: (bool value) { + if (value) { + settings.forbidUnknownConnections(); + } else { + settings.allowUnknownConnections(); + } + + // Save Settings... + saveSettings(context); + }, + activeTrackColor: settings.theme.defaultButtonColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(CwtchIcons.block_unknown, + color: settings.current().mainTextColor), + ), + SwitchListTile( + title: Text(AppLocalizations.of(context)! + .defaultPreserveHistorySetting), + subtitle: Text(AppLocalizations.of(context)! + .preserveHistorySettingDescription), + value: settings.preserveHistoryByDefault, + onChanged: (bool value) { + if (value) { + settings.setPreserveHistoryDefault(); + } else { + settings.setDeleteHistoryDefault(); + } + + // Save Settings... + saveSettings(context); + }, + activeTrackColor: settings.theme.defaultButtonColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(CwtchIcons.peer_history, + color: settings.current().mainTextColor), + ), + ])))), + + // ****** Experiments + Scrollbar( + key: Key("SettingsView"), + trackVisibility: true, + controller: settingsListScrollController, + child: SingleChildScrollView( + clipBehavior: Clip.antiAlias, + controller: settingsListScrollController, + padding: EdgeInsets.symmetric(vertical: 0, horizontal: 20), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, ), - Visibility( - visible: EnvironmentConfig.BUILD_VER == dev_version, - child: FutureBuilder( - future: Provider.of(context).cwtch.PlatformChannelInfo(), - builder: (context, snapshot) { - if (snapshot.hasData) { - HashMap data = snapshot.data as HashMap; - return getPlatformInfo(settings, data); + child: Column(children: [ + SwitchListTile( + title: Text( + AppLocalizations.of(context)!.experimentsEnabled), + subtitle: Text(AppLocalizations.of(context)! + .descriptionExperiments), + value: settings.experimentsEnabled, + onChanged: (bool value) { + if (value) { + settings.enableExperiments(); + } else { + settings.disableExperiments(); + } + // Save Settings... + saveSettings(context); + }, + activeTrackColor: settings.theme.defaultButtonColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(CwtchIcons.enable_experiments, + color: settings.current().mainTextColor), + ), + Visibility( + visible: settings.experimentsEnabled, + child: Column( + children: [ + SwitchListTile( + title: Text(AppLocalizations.of(context)! + .enableGroups), + subtitle: Text(AppLocalizations.of(context)! + .descriptionExperimentsGroups), + value: settings.isExperimentEnabled( + TapirGroupsExperiment), + onChanged: (bool value) { + if (value) { + settings.enableExperiment( + TapirGroupsExperiment); + } else { + settings.disableExperiment( + TapirGroupsExperiment); + } + // Save Settings... + saveSettings(context); + }, + activeTrackColor: + settings.theme.defaultButtonColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(CwtchIcons.enable_groups, + color: settings.current().mainTextColor), + ), + Visibility( + visible: + !Platform.isAndroid && !Platform.isIOS, + child: SwitchListTile( + title: Text(AppLocalizations.of(context)! + .settingServers), + subtitle: Provider.of( + context, + listen: false) + .cwtch + .IsServersCompiled() + ? Text(AppLocalizations.of(context)! + .settingServersDescription) + : Text( + "This version of Cwtch has been compiled without support for the server hosting experiment."), + value: Provider.of(context, + listen: false) + .cwtch + .IsServersCompiled() && + settings.isExperimentEnabled( + ServerManagementExperiment), + onChanged: Provider.of( + context, + listen: false) + .cwtch + .IsServersCompiled() + ? (bool value) { + Provider.of( + context, + listen: false) + .clear(); + if (value) { + settings.enableExperiment( + ServerManagementExperiment); + } else { + settings.disableExperiment( + ServerManagementExperiment); + } + // Save Settings... + saveSettings(context); + } + : null, + activeTrackColor: + settings.theme.defaultButtonColor, + inactiveTrackColor: settings + .theme.defaultButtonDisabledColor, + inactiveThumbColor: settings + .theme.defaultButtonDisabledColor, + secondary: Icon(CwtchIcons.dns_24px), + )), + SwitchListTile( + title: Text(AppLocalizations.of(context)! + .settingFileSharing), + subtitle: Text(AppLocalizations.of(context)! + .descriptionFileSharing), + value: settings.isExperimentEnabled( + FileSharingExperiment), + onChanged: (bool value) { + if (value) { + if (checkDownloadDirectory( + context, settings)) { + settings.enableExperiment( + FileSharingExperiment); + } else { + settings.enableExperiment( + FileSharingExperiment); + settings.disableExperiment( + ImagePreviewsExperiment); + } + } else { + settings.disableExperiment( + FileSharingExperiment); + settings.disableExperiment( + ImagePreviewsExperiment); + } + saveSettings(context); + }, + activeTrackColor: + settings.theme.defaultButtonColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(CwtchIcons.attached_file_3, + color: settings.current().mainTextColor), + ), + Visibility( + visible: settings.isExperimentEnabled( + FileSharingExperiment), + child: Column(children: [ + SwitchListTile( + title: Text(AppLocalizations.of(context)! + .settingImagePreviews), + subtitle: Text( + AppLocalizations.of(context)! + .settingImagePreviewsDescription), + value: settings.isExperimentEnabled( + ImagePreviewsExperiment), + onChanged: (bool value) { + if (value) { + if (checkDownloadDirectory( + context, settings)) { + settings.enableExperiment( + ImagePreviewsExperiment); + } else { + settings.disableExperiment( + ImagePreviewsExperiment); + } + } else { + settings.disableExperiment( + ImagePreviewsExperiment); + } + saveSettings(context); + }, + activeTrackColor: settings + .theme.defaultButtonActiveColor, + inactiveTrackColor: settings + .theme.defaultButtonDisabledColor, + secondary: Icon(Icons.photo, + color: + settings.current().mainTextColor), + ), + Visibility( + visible: settings.isExperimentEnabled( + ImagePreviewsExperiment) && + !Platform.isAndroid, + child: CwtchFolderPicker( + testKey: Key("DownloadFolderPicker"), + label: AppLocalizations.of(context)! + .settingDownloadFolder, + initialValue: settings.downloadPath, + textStyle: settings.scaleFonts( + defaultDropDownMenuItemTextStyle), + description: AppLocalizations.of( + context)! + .fileSharingSettingsDownloadFolderDescription, + tooltip: AppLocalizations.of(context)! + .fileSharingSettingsDownloadFolderTooltip, + onSave: (newVal) { + settings.downloadPath = newVal; + saveSettings(context); + }, + ), + ), + ]), + ), + SwitchListTile( + title: Text(AppLocalizations.of(context)! + .blodeuweddExperimentEnable), + subtitle: Provider.of(context, + listen: false) + .cwtch + .IsBlodeuweddSupported() + ? Text(AppLocalizations.of(context)! + .blodeuweddDescription) + : Text(AppLocalizations.of(context)! + .blodeuweddNotSupported), + value: Provider.of(context, + listen: false) + .cwtch + .IsBlodeuweddSupported() && + settings.isExperimentEnabled( + BlodeuweddExperiment), + onChanged: Provider.of(context, + listen: false) + .cwtch + .IsBlodeuweddSupported() + ? (bool value) { + if (value) { + settings.enableExperiment( + BlodeuweddExperiment); + } else { + settings.disableExperiment( + BlodeuweddExperiment); + } + saveSettings(context); + } + : null, + activeTrackColor: + settings.theme.defaultButtonColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + inactiveThumbColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(Icons.assistant, + color: settings.current().mainTextColor), + ), + Visibility( + visible: Provider.of(context, + listen: false) + .cwtch + .IsBlodeuweddSupported() && + settings.isExperimentEnabled( + BlodeuweddExperiment), + child: CwtchFolderPicker( + testKey: Key("DownloadFolderPicker"), + label: AppLocalizations.of(context)! + .settingDownloadFolder, + initialValue: settings.blodeuweddPath, + description: AppLocalizations.of(context)! + .blodeuweddPath, + tooltip: AppLocalizations.of(context)! + .blodeuweddPath, + onSave: (newVal) { + settings.blodeuweddPath = newVal; + saveSettings(context); + }, + ), + ), + ], + )), + Visibility( + visible: settings.experimentsEnabled, + child: SwitchListTile( + title: Text(AppLocalizations.of(context)! + .enableExperimentClickableLinks), + subtitle: Text(AppLocalizations.of(context)! + .experimentClickableLinksDescription), + value: settings.isExperimentEnabled( + ClickableLinksExperiment), + onChanged: (bool value) { + if (value) { + settings.enableExperiment( + ClickableLinksExperiment); + } else { + settings.disableExperiment( + ClickableLinksExperiment); } + saveSettings(context); + }, + activeTrackColor: + settings.theme.defaultButtonActiveColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(Icons.link, + color: settings.current().mainTextColor), + )), + Visibility( + visible: settings.experimentsEnabled, + child: SwitchListTile( + title: Text(AppLocalizations.of(context)! + .enableExperimentQRCode), + subtitle: Text(AppLocalizations.of(context)! + .experimentQRCodeDescription), + value: settings + .isExperimentEnabled(QRCodeExperiment), + onChanged: (bool value) { + if (value) { + settings.enableExperiment(QRCodeExperiment); + } else { + settings.disableExperiment(QRCodeExperiment); + } + saveSettings(context); + }, + activeTrackColor: + settings.theme.defaultButtonActiveColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(Icons.qr_code, + color: settings.current().mainTextColor), + )), + ])))), + + // **** About + Scrollbar( + key: Key("SettingsView"), + trackVisibility: true, + controller: settingsListScrollController, + child: SingleChildScrollView( + clipBehavior: Clip.antiAlias, + controller: settingsListScrollController, + padding: EdgeInsets.symmetric(vertical: 0, horizontal: 20), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Column(children: [ + AboutListTile( + icon: appIcon, + applicationIcon: Padding( + padding: EdgeInsets.all(5), + child: Icon(CwtchIcons.cwtch_knott)), + applicationName: "Cwtch UI", + applicationLegalese: + '\u{a9} 2021-2023 Open Privacy Research Society', + aboutBoxChildren: [ + Padding( + padding: EdgeInsets.fromLTRB( + 24.0 + 10.0 + (appIcon.size ?? 24.0), + 16.0, + 0.0, + 0.0), + // About has 24 padding (ln 389) and there appears to be another 10 of padding in the widget + child: SelectableText( + AppLocalizations.of(context)! + .versionBuilddate + .replaceAll( + "%1", EnvironmentConfig.BUILD_VER) + .replaceAll("%2", + EnvironmentConfig.BUILD_DATE)), + ) + ]), + SwitchListTile( + // TODO: Translate, Remove, OR Hide Prior to Release + title: Text("Show Performance Overlay"), + subtitle: + Text("Display an overlay graph of render time."), + value: settings.profileMode, + onChanged: (bool value) { + setState(() { + if (value) { + settings.profileMode = value; + } else { + settings.profileMode = value; + } + }); + }, + activeTrackColor: + settings.theme.defaultButtonActiveColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(Icons.bar_chart, + color: settings.current().mainTextColor), + ), + Visibility( + visible: + EnvironmentConfig.BUILD_VER == dev_version && + !Platform.isAndroid, + child: SwitchListTile( + title: Text("Show Semantic Debugger"), + subtitle: + Text("Show Accessibility Debugging View"), + value: settings.useSemanticDebugger, + onChanged: (bool value) { + if (value) { + settings.useSemanticDebugger = value; + } else { + settings.useSemanticDebugger = value; + } + saveSettings(context); + }, + activeTrackColor: + settings.theme.defaultButtonActiveColor, + inactiveTrackColor: + settings.theme.defaultButtonDisabledColor, + secondary: Icon(Icons.settings_accessibility, + color: settings.current().mainTextColor), + )), + Visibility( + visible: EnvironmentConfig.BUILD_VER == dev_version && + !Platform.isAndroid, + child: FutureBuilder( + future: + EnvironmentConfig.BUILD_VER != dev_version || + Platform.isAndroid + ? null + : Provider.of(context) + .cwtch + .GetDebugInfo(), + builder: (context, snapshot) { + if (snapshot.hasData) { + return Column( + children: [ + Text("libCwtch Debug Info: " + + snapshot.data.toString()), + Text("Message Cache Size (Mb): " + + (Provider.of(context) + .profs + .cacheMemUsage() / + (1024 * 1024)) + .toString()) + ], + ); + } else { return Container(); - })) - ])))); + } + }, + ), + ), + Visibility( + visible: EnvironmentConfig.BUILD_VER == dev_version, + child: FutureBuilder( + future: Provider.of(context) + .cwtch + .PlatformChannelInfo(), + builder: (context, snapshot) { + if (snapshot.hasData) { + HashMap data = snapshot.data + as HashMap; + return getPlatformInfo(settings, data); + } + return Container(); + })) + ])))) + ]); }); }); } @@ -653,7 +969,8 @@ class _GlobalSettingsViewState extends State { // set up the AlertDialog AlertDialog alert = AlertDialog( - title: Text(AppLocalizations.of(context)!.settingsAndroidPowerReenablePopup), + title: + Text(AppLocalizations.of(context)!.settingsAndroidPowerReenablePopup), actions: [ okButton, ], @@ -690,7 +1007,9 @@ bool checkDownloadDirectory(context, settings) { if (settings.downloadPath != "") { } else { // check if the default download path exists - var path = Provider.of(context, listen: false).cwtch.defaultDownloadPath(); + var path = Provider.of(context, listen: false) + .cwtch + .defaultDownloadPath(); if (path != null) { settings.downloadPath = path; } else { @@ -702,7 +1021,8 @@ bool checkDownloadDirectory(context, settings) { return true; } else { final snackBar = SnackBar( - content: Text(AppLocalizations.of(context)!.errorDownloadDirectoryDoesNotExist), + content: Text( + AppLocalizations.of(context)!.errorDownloadDirectoryDoesNotExist), ); ScaffoldMessenger.of(context).showSnackBar(snackBar); return false; @@ -825,5 +1145,7 @@ String getThemeName(context, String theme) { /// Send an UpdateGlobalSettings to the Event Bus saveSettings(context) { var settings = Provider.of(context, listen: false); - Provider.of(context, listen: false).cwtch.UpdateSettings(jsonEncode(settings.asJson())); + Provider.of(context, listen: false) + .cwtch + .UpdateSettings(jsonEncode(settings.asJson())); }