split settings panes into seperate files
continuous-integration/drone/pr Build is passing
Details
continuous-integration/drone/pr Build is passing
Details
This commit is contained in:
parent
2abbf223b2
commit
04985ee7eb
|
@ -0,0 +1,197 @@
|
||||||
|
import 'dart:collection';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
import '../config.dart';
|
||||||
|
import '../cwtch_icons_icons.dart';
|
||||||
|
import '../main.dart';
|
||||||
|
import '../settings.dart';
|
||||||
|
import '../themes/opaque.dart';
|
||||||
|
import 'globalsettingsview.dart';
|
||||||
|
|
||||||
|
class GlobalSettingsAboutView extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_GlobalSettingsAboutViewState createState() => _GlobalSettingsAboutViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GlobalSettingsAboutViewState extends State<GlobalSettingsAboutView> {
|
||||||
|
|
||||||
|
ScrollController settingsListScrollController = ScrollController();
|
||||||
|
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Consumer<Settings>(builder: (ccontext, settings, child) {
|
||||||
|
return LayoutBuilder(
|
||||||
|
builder: (BuildContext context, BoxConstraints viewportConstraints) {
|
||||||
|
var appIcon = Icon(Icons.info, color: settings
|
||||||
|
.current()
|
||||||
|
.mainTextColor);
|
||||||
|
return Scrollbar(
|
||||||
|
key: Key("AboutSettingsView"),
|
||||||
|
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: <Widget>[
|
||||||
|
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<FlwtchState>(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<FlwtchState>(context)
|
||||||
|
.profs
|
||||||
|
.cacheMemUsage() /
|
||||||
|
(1024 * 1024))
|
||||||
|
.toString())
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Visibility(
|
||||||
|
visible: EnvironmentConfig.BUILD_VER == dev_version,
|
||||||
|
child: FutureBuilder(
|
||||||
|
future: Provider
|
||||||
|
.of<FlwtchState>(context)
|
||||||
|
.cwtch
|
||||||
|
.PlatformChannelInfo(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
HashMap<String, String> data = snapshot.data
|
||||||
|
as HashMap<String, String>;
|
||||||
|
return getPlatformInfo(settings, data);
|
||||||
|
}
|
||||||
|
return Container();
|
||||||
|
}))
|
||||||
|
]))));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getPlatformInfo(settings, HashMap<String, String> platformChannelInfo) {
|
||||||
|
var sortedKeys = platformChannelInfo.keys.toList();
|
||||||
|
sortedKeys.sort();
|
||||||
|
var widgets = List<Widget>.empty(growable: true);
|
||||||
|
sortedKeys.forEach((element) {
|
||||||
|
widgets.add(ListTile(
|
||||||
|
leading: Icon(Icons.android, color: settings.current().mainTextColor),
|
||||||
|
title: Text(element),
|
||||||
|
subtitle: Text(platformChannelInfo[element]!),
|
||||||
|
));
|
||||||
|
});
|
||||||
|
return Column(
|
||||||
|
children: widgets,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: deprecated ?
|
||||||
|
/// Construct a version string from Package Info
|
||||||
|
String constructVersionString(PackageInfo pinfo) {
|
||||||
|
if (pinfo == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return pinfo.version + "." + pinfo.buildNumber;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,420 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
import '../config.dart';
|
||||||
|
import '../cwtch_icons_icons.dart';
|
||||||
|
import '../settings.dart';
|
||||||
|
import '../themes/cwtch.dart';
|
||||||
|
import '../themes/opaque.dart';
|
||||||
|
import 'globalsettingsview.dart';
|
||||||
|
|
||||||
|
class GlobalSettingsAppearanceView extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_GlobalSettingsAppearanceViewState createState() => _GlobalSettingsAppearanceViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GlobalSettingsAppearanceViewState extends State<GlobalSettingsAppearanceView> {
|
||||||
|
|
||||||
|
ScrollController settingsListScrollController = ScrollController();
|
||||||
|
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Consumer<Settings>(builder: (ccontext, settings, child) {
|
||||||
|
return LayoutBuilder(
|
||||||
|
builder: (BuildContext context, BoxConstraints viewportConstraints) {
|
||||||
|
return Scrollbar(
|
||||||
|
key: Key("AppearanceSettingsView"),
|
||||||
|
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<Settings>(context)
|
||||||
|
.locale
|
||||||
|
.toString(),
|
||||||
|
onChanged: (String? newValue) {
|
||||||
|
setState(() {
|
||||||
|
EnvironmentConfig.debugLog(
|
||||||
|
"setting language: $newValue");
|
||||||
|
settings.switchLocaleByCode(newValue!);
|
||||||
|
saveSettings(context);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
items: AppLocalizations.supportedLocales
|
||||||
|
.map<DropdownMenuItem<String>>(
|
||||||
|
(Locale value) {
|
||||||
|
return DropdownMenuItem<String>(
|
||||||
|
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<String>(
|
||||||
|
key: Key("DropdownTheme"),
|
||||||
|
isExpanded: true,
|
||||||
|
value: Provider
|
||||||
|
.of<Settings>(context)
|
||||||
|
.theme
|
||||||
|
.theme,
|
||||||
|
onChanged: (String? newValue) {
|
||||||
|
setState(() {
|
||||||
|
settings.setTheme(
|
||||||
|
newValue!, settings.theme.mode);
|
||||||
|
saveSettings(context);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
items: themes.keys
|
||||||
|
.map<DropdownMenuItem<String>>(
|
||||||
|
(String themeId) {
|
||||||
|
return DropdownMenuItem<String>(
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
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<DropdownMenuItem<String>>(
|
||||||
|
(DualpaneMode value) {
|
||||||
|
return DropdownMenuItem<String>(
|
||||||
|
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<DropdownMenuItem<String>>(
|
||||||
|
(DualpaneMode value) {
|
||||||
|
return DropdownMenuItem<String>(
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
]))));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A slightly verbose way to extract the full language name from
|
||||||
|
/// an individual language code. There might be a more efficient way of doing this.
|
||||||
|
String getLanguageFull(context, String languageCode, String? countryCode) {
|
||||||
|
if (languageCode == "en") {
|
||||||
|
return AppLocalizations.of(context)!.localeEn;
|
||||||
|
}
|
||||||
|
if (languageCode == "es") {
|
||||||
|
return AppLocalizations.of(context)!.localeEs;
|
||||||
|
}
|
||||||
|
if (languageCode == "fr") {
|
||||||
|
return AppLocalizations.of(context)!.localeFr;
|
||||||
|
}
|
||||||
|
if (languageCode == "pt" && countryCode == "BR") {
|
||||||
|
return AppLocalizations.of(context)!.localePtBr;
|
||||||
|
}
|
||||||
|
if (languageCode == "pt") {
|
||||||
|
return AppLocalizations.of(context)!.localePt;
|
||||||
|
}
|
||||||
|
if (languageCode == "de") {
|
||||||
|
return AppLocalizations.of(context)!.localeDe;
|
||||||
|
}
|
||||||
|
if (languageCode == "el") {
|
||||||
|
return AppLocalizations.of(context)!.localeEl;
|
||||||
|
}
|
||||||
|
if (languageCode == "it") {
|
||||||
|
return AppLocalizations.of(context)!.localeIt;
|
||||||
|
}
|
||||||
|
if (languageCode == "no") {
|
||||||
|
return AppLocalizations.of(context)!.localeNo;
|
||||||
|
}
|
||||||
|
if (languageCode == "pl") {
|
||||||
|
return AppLocalizations.of(context)!.localePl;
|
||||||
|
}
|
||||||
|
if (languageCode == "lb") {
|
||||||
|
return AppLocalizations.of(context)!.localeLb;
|
||||||
|
}
|
||||||
|
if (languageCode == "ru") {
|
||||||
|
return AppLocalizations.of(context)!.localeRU;
|
||||||
|
}
|
||||||
|
if (languageCode == "ro") {
|
||||||
|
return AppLocalizations.of(context)!.localeRo;
|
||||||
|
}
|
||||||
|
if (languageCode == "cy") {
|
||||||
|
return AppLocalizations.of(context)!.localeCy;
|
||||||
|
}
|
||||||
|
if (languageCode == "da") {
|
||||||
|
return AppLocalizations.of(context)!.localeDa;
|
||||||
|
}
|
||||||
|
if (languageCode == "tr") {
|
||||||
|
return AppLocalizations.of(context)!.localeTr;
|
||||||
|
}
|
||||||
|
if (languageCode == "nl") {
|
||||||
|
return AppLocalizations.of(context)!.localeNl;
|
||||||
|
}
|
||||||
|
if (languageCode == "sk") {
|
||||||
|
return AppLocalizations.of(context)!.localeSk;
|
||||||
|
}
|
||||||
|
if (languageCode == "ko") {
|
||||||
|
return AppLocalizations.of(context)!.localeKo;
|
||||||
|
}
|
||||||
|
if (languageCode == "ja") {
|
||||||
|
return AppLocalizations.of(context)!.localeJa;
|
||||||
|
}
|
||||||
|
if (languageCode == "sv") {
|
||||||
|
return AppLocalizations.of(context)!.localeSv;
|
||||||
|
}
|
||||||
|
if (languageCode == "sw") {
|
||||||
|
return AppLocalizations.of(context)!.localeSw;
|
||||||
|
}
|
||||||
|
if (languageCode == "uk") {
|
||||||
|
return AppLocalizations.of(context)!.localeUk;
|
||||||
|
}
|
||||||
|
if (languageCode == "uz") {
|
||||||
|
return AppLocalizations.of(context)!.localeUzbek;
|
||||||
|
}
|
||||||
|
return languageCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Since we don't seem to able to dynamically pull translations, this function maps themes to their names
|
||||||
|
String getThemeName(context, String theme) {
|
||||||
|
switch (theme) {
|
||||||
|
case cwtch_theme:
|
||||||
|
return AppLocalizations.of(context)!.themeNameCwtch;
|
||||||
|
case "ghost":
|
||||||
|
return AppLocalizations.of(context)!.themeNameGhost;
|
||||||
|
case "mermaid":
|
||||||
|
return AppLocalizations.of(context)!.themeNameMermaid;
|
||||||
|
case "midnight":
|
||||||
|
return AppLocalizations.of(context)!.themeNameMidnight;
|
||||||
|
case "neon1":
|
||||||
|
return AppLocalizations.of(context)!.themeNameNeon1;
|
||||||
|
case "neon2":
|
||||||
|
return AppLocalizations.of(context)!.themeNameNeon2;
|
||||||
|
case "pumpkin":
|
||||||
|
return AppLocalizations.of(context)!.themeNamePumpkin;
|
||||||
|
case "vampire":
|
||||||
|
return AppLocalizations.of(context)!.themeNameVampire;
|
||||||
|
case "witch":
|
||||||
|
return AppLocalizations.of(context)!.themeNameWitch;
|
||||||
|
case "juniper":
|
||||||
|
return "Juniper"; // Juniper is a noun, and doesn't get subject to translation...
|
||||||
|
}
|
||||||
|
return theme;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,242 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
import '../config.dart';
|
||||||
|
import '../cwtch_icons_icons.dart';
|
||||||
|
import '../settings.dart';
|
||||||
|
import '../themes/opaque.dart';
|
||||||
|
import 'globalsettingsview.dart';
|
||||||
|
|
||||||
|
class GlobalSettingsBehaviourView extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_GlobalSettingsBehaviourViewState createState() => _GlobalSettingsBehaviourViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GlobalSettingsBehaviourViewState extends State<GlobalSettingsBehaviourView> {
|
||||||
|
static const androidSettingsChannel = const MethodChannel('androidSettings');
|
||||||
|
static const androidSettingsChangeChannel = const MethodChannel('androidSettingsChanged');
|
||||||
|
|
||||||
|
|
||||||
|
ScrollController settingsListScrollController = ScrollController();
|
||||||
|
bool powerExempt = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
androidSettingsChangeChannel.setMethodCallHandler(handleSettingsChanged);
|
||||||
|
|
||||||
|
if (Platform.isAndroid) {
|
||||||
|
isBatteryExempt().then((value) => setState(() {
|
||||||
|
powerExempt = value;
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
powerExempt = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler on method channel for MainActivity/onActivityResult to report the user choice when we ask for power exemption
|
||||||
|
Future<void> handleSettingsChanged(MethodCall call) async {
|
||||||
|
if (call.method == "powerExemptionChange") {
|
||||||
|
if (call.arguments) {
|
||||||
|
setState(() {
|
||||||
|
powerExempt = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//* Android Only Requests
|
||||||
|
|
||||||
|
Future<bool> isBatteryExempt() async {
|
||||||
|
return await androidSettingsChannel.invokeMethod('isBatteryExempt', {}) ??
|
||||||
|
false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> requestBatteryExemption() async {
|
||||||
|
await androidSettingsChannel.invokeMethod('requestBatteryExemption', {});
|
||||||
|
return Future.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
//* End Android Only Requests
|
||||||
|
|
||||||
|
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Consumer<Settings>(builder: (ccontext, settings, child) {
|
||||||
|
return LayoutBuilder(
|
||||||
|
builder: (BuildContext context, BoxConstraints viewportConstraints) {
|
||||||
|
return Scrollbar(
|
||||||
|
key: Key("BehaviourSettingsView"),
|
||||||
|
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: [
|
||||||
|
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<
|
||||||
|
DropdownMenuItem<NotificationPolicy>>(
|
||||||
|
(NotificationPolicy value) {
|
||||||
|
return DropdownMenuItem<NotificationPolicy>(
|
||||||
|
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<
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
]))));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
showBatteryDialog(BuildContext context) {
|
||||||
|
Widget okButton = ElevatedButton(
|
||||||
|
child: Text(AppLocalizations.of(context)!.okButton),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// set up the AlertDialog
|
||||||
|
AlertDialog alert = AlertDialog(
|
||||||
|
title:
|
||||||
|
Text(AppLocalizations.of(context)!.settingsAndroidPowerReenablePopup),
|
||||||
|
actions: [
|
||||||
|
okButton,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
// show the dialog
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return alert;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,403 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
import '../config.dart';
|
||||||
|
import '../cwtch_icons_icons.dart';
|
||||||
|
import '../main.dart';
|
||||||
|
import '../models/servers.dart';
|
||||||
|
import '../settings.dart';
|
||||||
|
import '../themes/opaque.dart';
|
||||||
|
import '../widgets/folderpicker.dart';
|
||||||
|
import 'globalsettingsview.dart';
|
||||||
|
|
||||||
|
class GlobalSettingsExperimentsView extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_GlobalSettingsExperimentsViewState createState() => _GlobalSettingsExperimentsViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GlobalSettingsExperimentsViewState extends State<GlobalSettingsExperimentsView> {
|
||||||
|
|
||||||
|
ScrollController settingsListScrollController = ScrollController();
|
||||||
|
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Consumer<Settings>(builder: (ccontext, settings, child) {
|
||||||
|
return LayoutBuilder(
|
||||||
|
builder: (BuildContext context, BoxConstraints viewportConstraints) {
|
||||||
|
return Scrollbar(
|
||||||
|
key: Key("ExperimentsSettingsView"),
|
||||||
|
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: [
|
||||||
|
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<FlwtchState>(
|
||||||
|
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<FlwtchState>(context,
|
||||||
|
listen: false)
|
||||||
|
.cwtch
|
||||||
|
.IsServersCompiled() &&
|
||||||
|
settings.isExperimentEnabled(
|
||||||
|
ServerManagementExperiment),
|
||||||
|
onChanged: Provider
|
||||||
|
.of<FlwtchState>(
|
||||||
|
context,
|
||||||
|
listen: false)
|
||||||
|
.cwtch
|
||||||
|
.IsServersCompiled()
|
||||||
|
? (bool value) {
|
||||||
|
Provider.of<ServerListState>(
|
||||||
|
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<FlwtchState>(context,
|
||||||
|
listen: false)
|
||||||
|
.cwtch
|
||||||
|
.IsBlodeuweddSupported()
|
||||||
|
? Text(AppLocalizations.of(context)!
|
||||||
|
.blodeuweddDescription)
|
||||||
|
: Text(AppLocalizations.of(context)!
|
||||||
|
.blodeuweddNotSupported),
|
||||||
|
value: Provider
|
||||||
|
.of<FlwtchState>(context,
|
||||||
|
listen: false)
|
||||||
|
.cwtch
|
||||||
|
.IsBlodeuweddSupported() &&
|
||||||
|
settings.isExperimentEnabled(
|
||||||
|
BlodeuweddExperiment),
|
||||||
|
onChanged: Provider
|
||||||
|
.of<FlwtchState>(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<FlwtchState>(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),
|
||||||
|
)),
|
||||||
|
]))));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkDownloadDirectory(context, settings) {
|
||||||
|
bool showError = false;
|
||||||
|
if (settings.downloadPath != "") {
|
||||||
|
} else {
|
||||||
|
// check if the default download path exists
|
||||||
|
var path = Provider.of<FlwtchState>(context, listen: false)
|
||||||
|
.cwtch
|
||||||
|
.defaultDownloadPath();
|
||||||
|
if (path != null) {
|
||||||
|
settings.downloadPath = path;
|
||||||
|
} else {
|
||||||
|
showError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!showError && Directory(settings.downloadPath).existsSync()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
final snackBar = SnackBar(
|
||||||
|
content: Text(
|
||||||
|
AppLocalizations.of(context)!.errorDownloadDirectoryDoesNotExist),
|
||||||
|
);
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue