Formatting + Font Scale Setting

This commit is contained in:
Sarah Jamie Lewis 2023-05-15 10:08:54 -07:00
parent 0b0a5095f1
commit d09b82db76
11 changed files with 88 additions and 106 deletions

View File

@ -410,6 +410,5 @@ class CwtchGomobile implements Cwtch {
@override @override
void AttemptReconnection(String profile, String onion) { void AttemptReconnection(String profile, String onion) {
cwtchPlatform.invokeMethod("PeerWithOnion", {"ProfileOnion": profile, "onion": onion}); cwtchPlatform.invokeMethod("PeerWithOnion", {"ProfileOnion": profile, "onion": onion});
} }
} }

View File

@ -32,7 +32,6 @@ import 'themes/opaque.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:intl/intl.dart' as intl; import 'package:intl/intl.dart' as intl;
var globalSettings = Settings(Locale("en", ''), CwtchDark()); var globalSettings = Settings(Locale("en", ''), CwtchDark());
@ -95,39 +94,15 @@ class FlwtchState extends State<Flwtch> with WindowListener {
shutdownLinuxMethodChannel.setMethodCallHandler(shutdownDirect); shutdownLinuxMethodChannel.setMethodCallHandler(shutdownDirect);
print("initState: creating cwtchnotifier, ffi"); print("initState: creating cwtchnotifier, ffi");
if (Platform.isAndroid) { if (Platform.isAndroid) {
var cwtchNotifier = new CwtchNotifier( var cwtchNotifier = new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, NullNotificationsManager(), globalAppState, globalServersList, this);
profs,
globalSettings,
globalErrorHandler,
globalTorStatus,
NullNotificationsManager(),
globalAppState,
globalServersList,
this);
cwtch = CwtchGomobile(cwtchNotifier); cwtch = CwtchGomobile(cwtchNotifier);
} else if (Platform.isLinux) { } else if (Platform.isLinux) {
var cwtchNotifier = var cwtchNotifier =
new CwtchNotifier( new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, newDesktopNotificationsManager(_notificationSelectConvo), globalAppState, globalServersList, this);
profs,
globalSettings,
globalErrorHandler,
globalTorStatus,
newDesktopNotificationsManager(_notificationSelectConvo),
globalAppState,
globalServersList,
this);
cwtch = CwtchFfi(cwtchNotifier); cwtch = CwtchFfi(cwtchNotifier);
} else { } else {
var cwtchNotifier = var cwtchNotifier =
new CwtchNotifier( new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, newDesktopNotificationsManager(_notificationSelectConvo), globalAppState, globalServersList, this);
profs,
globalSettings,
globalErrorHandler,
globalTorStatus,
newDesktopNotificationsManager(_notificationSelectConvo),
globalAppState,
globalServersList,
this);
cwtch = CwtchFfi(cwtchNotifier); cwtch = CwtchFfi(cwtchNotifier);
} }
startConnectivityListener(); startConnectivityListener();
@ -139,7 +114,7 @@ class FlwtchState extends State<Flwtch> with WindowListener {
// connectivity listening is an optional enhancement feature that tries to listen for OS events about the network // connectivity listening is an optional enhancement feature that tries to listen for OS events about the network
// and if it detects coming back online, restarts the ACN/tor // and if it detects coming back online, restarts the ACN/tor
// gracefully fails and NOPs, as it's not a required functionality // gracefully fails and NOPs, as it's not a required functionality
startConnectivityListener() async { startConnectivityListener() async {
try { try {
connectivityStream = await Connectivity().onConnectivityChanged.listen((ConnectivityResult result) { connectivityStream = await Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
// Got a new connectivity status! // Got a new connectivity status!

View File

@ -66,6 +66,7 @@ class Settings extends ChangeNotifier {
bool _useTorCache = false; bool _useTorCache = false;
String _torCacheDir = ""; String _torCacheDir = "";
bool _useSemanticDebugger = false; bool _useSemanticDebugger = false;
double _fontScaling = 1.0;
String get torCacheDir => _torCacheDir; String get torCacheDir => _torCacheDir;
@ -129,6 +130,9 @@ class Settings extends ChangeNotifier {
// Set Locale and notify listeners // Set Locale and notify listeners
switchLocaleByCode(settings["Locale"]); switchLocaleByCode(settings["Locale"]);
// Decide whether to enable Experiments
_fontScaling = double.parse(settings["FontScaling"].toString());
blockUnknownConnections = settings["BlockUnknownConnections"] ?? false; blockUnknownConnections = settings["BlockUnknownConnections"] ?? false;
streamerMode = settings["StreamerMode"] ?? false; streamerMode = settings["StreamerMode"] ?? false;
@ -180,6 +184,14 @@ class Settings extends ChangeNotifier {
} }
} }
/// Handle Font Scaling
set fontScaling(double newFontScaling) {
this._fontScaling = newFontScaling;
notifyListeners();
}
double get fontScaling => _fontScaling;
/// Switch the Locale of the App /// Switch the Locale of the App
switchLocale(Locale newLocale) { switchLocale(Locale newLocale) {
locale = newLocale; locale = newLocale;
@ -454,7 +466,8 @@ class Settings extends ChangeNotifier {
"CustomAuth": _customTorAuth, "CustomAuth": _customTorAuth,
"UseTorCache": _useTorCache, "UseTorCache": _useTorCache,
"TorCacheDir": _torCacheDir, "TorCacheDir": _torCacheDir,
"BlodeuweddPath": _blodeuweddPath "BlodeuweddPath": _blodeuweddPath,
"FontScaling": _fontScaling
}; };
} }
} }

View File

@ -7,8 +7,7 @@ import 'dart:async';
import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart';
// Export enums from the platform_interface so plugin users can use them directly. // Export enums from the platform_interface so plugin users can use them directly.
export 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart' export 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart' show ConnectivityResult;
show ConnectivityResult;
export 'src/connectivity_plus_linux.dart'; export 'src/connectivity_plus_linux.dart';

View File

@ -45,7 +45,6 @@ abstract class ConnectivityPlatform extends PlatformInterface {
/// Returns a Stream of ConnectivityResults changes. /// Returns a Stream of ConnectivityResults changes.
Stream<ConnectivityResult> get onConnectivityChanged { Stream<ConnectivityResult> get onConnectivityChanged {
throw UnimplementedError( throw UnimplementedError('get onConnectivityChanged has not been implemented.');
'get onConnectivityChanged has not been implemented.');
} }
} }

View File

@ -14,30 +14,23 @@ import 'src/utils.dart';
class MethodChannelConnectivity extends ConnectivityPlatform { class MethodChannelConnectivity extends ConnectivityPlatform {
/// The method channel used to interact with the native platform. /// The method channel used to interact with the native platform.
@visibleForTesting @visibleForTesting
MethodChannel methodChannel = MethodChannel methodChannel = const MethodChannel('dev.fluttercommunity.plus/connectivity');
const MethodChannel('dev.fluttercommunity.plus/connectivity');
/// The event channel used to receive ConnectivityResult changes from the native platform. /// The event channel used to receive ConnectivityResult changes from the native platform.
@visibleForTesting @visibleForTesting
EventChannel eventChannel = EventChannel eventChannel = const EventChannel('dev.fluttercommunity.plus/connectivity_status');
const EventChannel('dev.fluttercommunity.plus/connectivity_status');
Stream<ConnectivityResult>? _onConnectivityChanged; Stream<ConnectivityResult>? _onConnectivityChanged;
/// Fires whenever the connectivity state changes. /// Fires whenever the connectivity state changes.
@override @override
Stream<ConnectivityResult> get onConnectivityChanged { Stream<ConnectivityResult> get onConnectivityChanged {
_onConnectivityChanged ??= eventChannel _onConnectivityChanged ??= eventChannel.receiveBroadcastStream().map((dynamic result) => result.toString()).map(parseConnectivityResult);
.receiveBroadcastStream()
.map((dynamic result) => result.toString())
.map(parseConnectivityResult);
return _onConnectivityChanged!; return _onConnectivityChanged!;
} }
@override @override
Future<ConnectivityResult> checkConnectivity() { Future<ConnectivityResult> checkConnectivity() {
return methodChannel return methodChannel.invokeMethod<String>('check').then((value) => parseConnectivityResult(value ?? ''));
.invokeMethod<String>('check')
.then((value) => parseConnectivityResult(value ?? ''));
} }
} }

View File

@ -1,6 +1,5 @@
/// Connection status check result. /// Connection status check result.
enum ConnectivityResult { enum ConnectivityResult {
/// WiFi: Device connected via Wi-Fi /// WiFi: Device connected via Wi-Fi
wifi, wifi,

View File

@ -59,12 +59,10 @@ NetworkManagerConnectivityState _decodeConnectivityState(int value) {
class _NetworkManagerInterface { class _NetworkManagerInterface {
final Map<String, DBusValue> properties; final Map<String, DBusValue> properties;
final propertiesChangedStreamController = final propertiesChangedStreamController = StreamController<List<String>>.broadcast();
StreamController<List<String>>.broadcast();
/// Stream of property names as their values change. /// Stream of property names as their values change.
Stream<List<String>> get propertiesChanged => Stream<List<String>> get propertiesChanged => propertiesChangedStreamController.stream;
propertiesChangedStreamController.stream;
_NetworkManagerInterface(this.properties); _NetworkManagerInterface(this.properties);
@ -77,8 +75,7 @@ class _NetworkManagerInterface {
class _NetworkManagerObject extends DBusRemoteObject { class _NetworkManagerObject extends DBusRemoteObject {
final interfaces = <String, _NetworkManagerInterface>{}; final interfaces = <String, _NetworkManagerInterface>{};
void updateInterfaces( void updateInterfaces(Map<String, Map<String, DBusValue>> interfacesAndProperties) {
Map<String, Map<String, DBusValue>> interfacesAndProperties) {
interfacesAndProperties.forEach((interfaceName, properties) { interfacesAndProperties.forEach((interfaceName, properties) {
interfaces[interfaceName] = _NetworkManagerInterface(properties); interfaces[interfaceName] = _NetworkManagerInterface(properties);
}); });
@ -100,8 +97,7 @@ class _NetworkManagerObject extends DBusRemoteObject {
} }
} }
void updateProperties( void updateProperties(String interfaceName, Map<String, DBusValue> changedProperties) {
String interfaceName, Map<String, DBusValue> changedProperties) {
var interface = interfaces[interfaceName]; var interface = interfaces[interfaceName];
if (interface != null) { if (interface != null) {
interface.updateProperties(changedProperties); interface.updateProperties(changedProperties);
@ -210,10 +206,7 @@ class _NetworkManagerObject extends DBusRemoteObject {
if (value.signature != DBusSignature('as')) { if (value.signature != DBusSignature('as')) {
return null; return null;
} }
return (value as DBusArray) return (value as DBusArray).children.map((e) => (e as DBusString).value).toList();
.children
.map((e) => (e as DBusString).value)
.toList();
} }
/// Gets a cached object path property, or returns null if not present or not the correct type. /// Gets a cached object path property, or returns null if not present or not the correct type.
@ -229,8 +222,7 @@ class _NetworkManagerObject extends DBusRemoteObject {
} }
/// Gets a cached object path array property, or returns null if not present or not the correct type. /// Gets a cached object path array property, or returns null if not present or not the correct type.
List<DBusObjectPath>? getObjectPathArrayProperty( List<DBusObjectPath>? getObjectPathArrayProperty(String interface, String name) {
String interface, String name) {
var value = getCachedProperty(interface, name); var value = getCachedProperty(interface, name);
if (value == null) { if (value == null) {
return null; return null;
@ -238,15 +230,11 @@ class _NetworkManagerObject extends DBusRemoteObject {
if (value.signature != DBusSignature('ao')) { if (value.signature != DBusSignature('ao')) {
return null; return null;
} }
return (value as DBusArray) return (value as DBusArray).children.map((e) => (e as DBusObjectPath)).toList();
.children
.map((e) => (e as DBusObjectPath))
.toList();
} }
/// Gets a cached list of data property, or returns null if not present or not the correct type. /// Gets a cached list of data property, or returns null if not present or not the correct type.
List<Map<String, dynamic>>? getDataListProperty( List<Map<String, dynamic>>? getDataListProperty(String interface, String name) {
String interface, String name) {
var value = getCachedProperty(interface, name); var value = getCachedProperty(interface, name);
if (value == null) { if (value == null) {
return null; return null;
@ -261,22 +249,16 @@ class _NetworkManagerObject extends DBusRemoteObject {
)); ));
} }
return (value as DBusArray) return (value as DBusArray).children.map((value) => convertData(value)).toList();
.children
.map((value) => convertData(value))
.toList();
} }
_NetworkManagerObject(DBusClient client, DBusObjectPath path, _NetworkManagerObject(DBusClient client, DBusObjectPath path, Map<String, Map<String, DBusValue>> interfacesAndProperties) : super(client, name: 'org.freedesktop.NetworkManager', path: path) {
Map<String, Map<String, DBusValue>> interfacesAndProperties)
: super(client, name: 'org.freedesktop.NetworkManager', path: path) {
updateInterfaces(interfacesAndProperties); updateInterfaces(interfacesAndProperties);
} }
} }
/// A client that connects to NetworkManager. /// A client that connects to NetworkManager.
class NetworkManagerClient { class NetworkManagerClient {
/// The bus this client is connected to. /// The bus this client is connected to.
final DBusClient _bus; final DBusClient _bus;
final bool _closeBus; final bool _closeBus;
@ -302,10 +284,7 @@ class NetworkManagerClient {
} }
/// Stream of property names as their values change. /// Stream of property names as their values change.
Stream<List<String>> get propertiesChanged => Stream<List<String>> get propertiesChanged => _manager?.interfaces[_managerInterfaceName]?.propertiesChangedStreamController.stream ?? Stream<List<String>>.empty();
_manager?.interfaces[_managerInterfaceName]
?.propertiesChangedStreamController.stream ??
Stream<List<String>>.empty();
/// Connects to the NetworkManager D-Bus objects. /// Connects to the NetworkManager D-Bus objects.
/// Must be called before accessing methods and properties. /// Must be called before accessing methods and properties.
@ -333,8 +312,7 @@ class NetworkManagerClient {
if (object != null) { if (object != null) {
object.updateInterfaces(signal.interfacesAndProperties); object.updateInterfaces(signal.interfacesAndProperties);
} else { } else {
object = _NetworkManagerObject( object = _NetworkManagerObject(_bus, signal.changedPath, signal.interfacesAndProperties);
_bus, signal.changedPath, signal.interfacesAndProperties);
_objects[signal.changedPath] = object; _objects[signal.changedPath] = object;
} }
} else if (signal is DBusObjectManagerInterfacesRemovedSignal) { } else if (signal is DBusObjectManagerInterfacesRemovedSignal) {
@ -351,8 +329,7 @@ class NetworkManagerClient {
} else if (signal is DBusPropertiesChangedSignal) { } else if (signal is DBusPropertiesChangedSignal) {
var object = _objects[signal.path]; var object = _objects[signal.path];
if (object != null) { if (object != null) {
object.updateProperties( object.updateProperties(signal.propertiesInterface, signal.changedProperties);
signal.propertiesInterface, signal.changedProperties);
} }
} }
}); });
@ -360,8 +337,7 @@ class NetworkManagerClient {
// Find all the objects exported. // Find all the objects exported.
var objects = await _root.getManagedObjects(); var objects = await _root.getManagedObjects();
objects.forEach((objectPath, interfacesAndProperties) { objects.forEach((objectPath, interfacesAndProperties) {
_objects[objectPath] = _objects[objectPath] = _NetworkManagerObject(_bus, objectPath, interfacesAndProperties);
_NetworkManagerObject(_bus, objectPath, interfacesAndProperties);
}); });
} }
@ -376,8 +352,7 @@ class NetworkManagerClient {
/// True is NetworkManager is still starting up. /// True is NetworkManager is still starting up.
bool get startup { bool get startup {
return _manager?.getBooleanProperty(_managerInterfaceName, 'Startup') ?? return _manager?.getBooleanProperty(_managerInterfaceName, 'Startup') ?? false;
false;
} }
/// The version of NetworkManager running. /// The version of NetworkManager running.
@ -387,20 +362,17 @@ class NetworkManagerClient {
/// The result of the last connectivity check. /// The result of the last connectivity check.
NetworkManagerConnectivityState get connectivity { NetworkManagerConnectivityState get connectivity {
var value = var value = _manager?.getUint32Property(_managerInterfaceName, 'Connectivity') ?? 0;
_manager?.getUint32Property(_managerInterfaceName, 'Connectivity') ?? 0;
return _decodeConnectivityState(value); return _decodeConnectivityState(value);
} }
/// The overall networking state. /// The overall networking state.
NetworkManagerState get state { NetworkManagerState get state {
var value = var value = _manager?.getUint32Property(_managerInterfaceName, 'State') ?? 0;
_manager?.getUint32Property(_managerInterfaceName, 'State') ?? 0;
return _decodeState(value); return _decodeState(value);
} }
_NetworkManagerObject? get _manager => _NetworkManagerObject? get _manager => _objects[DBusObjectPath('/org/freedesktop/NetworkManager')];
_objects[DBusObjectPath('/org/freedesktop/NetworkManager')];
/// Terminates all active connections. If a client remains unclosed, the Dart process may not terminate. /// Terminates all active connections. If a client remains unclosed, the Dart process may not terminate.
Future<void> close() async { Future<void> close() async {

View File

@ -216,6 +216,27 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
), ),
); );
}).toList())))), }).toList())))),
ListTile(
title: Text(AppLocalizations.of(context)!.defaultScalingText, style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(AppLocalizations.of(context)!.defaultScalingText),
trailing: Container(
width: MediaQuery.of(context).size.width / 4,
child: Slider(
onChanged: (double value) {
settings.fontScaling = value;
// Save Settings...
saveSettings(context);
},
min: -1.0,
divisions: 10,
max: 2.0,
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( SwitchListTile(
title: Text(AppLocalizations.of(context)!.streamerModeLabel, style: TextStyle(color: settings.current().mainTextColor)), title: Text(AppLocalizations.of(context)!.streamerModeLabel, style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(AppLocalizations.of(context)!.descriptionStreamerMode), subtitle: Text(AppLocalizations.of(context)!.descriptionStreamerMode),

View File

@ -46,15 +46,21 @@ class _MessageListState extends State<MessageList> {
// With the message cache in place this is no longer necessary // With the message cache in place this is no longer necessary
bool loadMessages = true; bool loadMessages = true;
var reconnectButton = Visibility(visible: isP2P, child: Padding(padding: EdgeInsets.all(2), child: Tooltip( var reconnectButton = Visibility(
message: AppLocalizations.of(context)!.retryConnectionTooltip, visible: isP2P,
child:ElevatedButton( child: Padding(
style: ButtonStyle(padding: MaterialStateProperty.all(EdgeInsets.all(20))), padding: EdgeInsets.all(2),
child: Text(AppLocalizations.of(context)!.retryConnection), child: Tooltip(
onPressed: () { message: AppLocalizations.of(context)!.retryConnectionTooltip,
Provider.of<FlwtchState>(context, listen: false).cwtch.AttemptReconnection(Provider.of<ProfileInfoState>(context,listen: false).onion, Provider.of<ContactInfoState>(context, listen: false).onion); child: ElevatedButton(
}, style: ButtonStyle(padding: MaterialStateProperty.all(EdgeInsets.all(20))),
)))); child: Text(AppLocalizations.of(context)!.retryConnection),
onPressed: () {
Provider.of<FlwtchState>(context, listen: false)
.cwtch
.AttemptReconnection(Provider.of<ProfileInfoState>(context, listen: false).onion, Provider.of<ContactInfoState>(context, listen: false).onion);
},
))));
return RepaintBoundary( return RepaintBoundary(
child: Container( child: Container(
@ -70,8 +76,14 @@ class _MessageListState extends State<MessageList> {
child: showSyncing child: showSyncing
? Text(AppLocalizations.of(context)!.serverNotSynced, textAlign: TextAlign.center) ? Text(AppLocalizations.of(context)!.serverNotSynced, textAlign: TextAlign.center)
: showOfflineWarning : showOfflineWarning
? Column(crossAxisAlignment: CrossAxisAlignment.center, children: [Text(Provider.of<ContactInfoState>(context).isGroup ? AppLocalizations.of(context)!.serverConnectivityDisconnected : AppLocalizations.of(context)!.peerOfflineMessage, ? Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
textAlign: TextAlign.center), reconnectButton]) Text(
Provider.of<ContactInfoState>(context).isGroup
? AppLocalizations.of(context)!.serverConnectivityDisconnected
: AppLocalizations.of(context)!.peerOfflineMessage,
textAlign: TextAlign.center),
reconnectButton
])
// Only show the ephemeral status for peer conversations, not for groups... // Only show the ephemeral status for peer conversations, not for groups...
: (showEphemeralWarning : (showEphemeralWarning
? Text(AppLocalizations.of(context)!.chatHistoryDefault, textAlign: TextAlign.center) ? Text(AppLocalizations.of(context)!.chatHistoryDefault, textAlign: TextAlign.center)