diff --git a/LIBCWTCH-GO-MACOS.version b/LIBCWTCH-GO-MACOS.version index f0e5617e..4fc8a725 100644 --- a/LIBCWTCH-GO-MACOS.version +++ b/LIBCWTCH-GO-MACOS.version @@ -1 +1 @@ -2022-04-04-17-46-v1.6.0-15-g97defdf +2022-04-14-18-14-v.1.7.0-2-g9901e08 \ No newline at end of file diff --git a/LIBCWTCH-GO.version b/LIBCWTCH-GO.version index 4b001196..27059d83 100644 --- a/LIBCWTCH-GO.version +++ b/LIBCWTCH-GO.version @@ -1 +1 @@ -2022-04-04-21-46-v1.6.0-15-g97defdf \ No newline at end of file +2022-04-14-22-15-v.1.7.0-2-g9901e08 \ No newline at end of file diff --git a/lib/cwtch/cwtch.dart b/lib/cwtch/cwtch.dart index d42be68b..fffc4fc8 100644 --- a/lib/cwtch/cwtch.dart +++ b/lib/cwtch/cwtch.dart @@ -118,4 +118,6 @@ abstract class Cwtch { void l10nInit(String notificationSimple, String notificationConversationInfo); void dispose(); + + Future GetDebugInfo(); } diff --git a/lib/cwtch/ffi.dart b/lib/cwtch/ffi.dart index 2edb3faa..e0c583bc 100644 --- a/lib/cwtch/ffi.dart +++ b/lib/cwtch/ffi.dart @@ -102,6 +102,9 @@ typedef VoidFromStringIntIntFn = void Function(Pointer, int, int, int); typedef appbus_events_function = Pointer Function(); typedef AppbusEventsFn = Pointer Function(); +typedef void_to_string = Pointer Function(); +typedef StringFromVoid = Pointer Function(); + const String UNSUPPORTED_OS = "unsupported-os"; class CwtchFfi implements Cwtch { @@ -817,4 +820,14 @@ class CwtchFfi implements Cwtch { malloc.free(utf8file); return importResult; } + + @override + Future GetDebugInfo() async { + var getDebugInfo = library.lookup>("c_GetDebugInfo"); + final GetDebugInfo = getDebugInfo.asFunction(); + Pointer result = GetDebugInfo(); + String debugResult = result.toDartString(); + _UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(result); + return debugResult; + } } diff --git a/lib/cwtch/gomobile.dart b/lib/cwtch/gomobile.dart index 7bd4f888..1e1aaed5 100644 --- a/lib/cwtch/gomobile.dart +++ b/lib/cwtch/gomobile.dart @@ -326,4 +326,11 @@ class CwtchGomobile implements Cwtch { Future ImportProfile(String file, String pass) { return cwtchPlatform.invokeMethod("ImportProfile", {"file": file, "pass": pass}); } + + @override + Future GetDebugInfo() { + // FIXME: getDebugInfo is less useful for Android so for now + // we just assume it will always be called from desktop... + throw UnimplementedError(); + } } diff --git a/lib/models/contactlist.dart b/lib/models/contactlist.dart index 92ecc12d..835b6161 100644 --- a/lib/models/contactlist.dart +++ b/lib/models/contactlist.dart @@ -127,4 +127,8 @@ class ContactListState extends ChangeNotifier { getContact(identifier)?.newMessage(identifier, messageID, timestamp, senderHandle, senderImage, isAuto, data, contenthash, selectedConversation); updateLastMessageTime(identifier, DateTime.now()); } + + int cacheMemUsage() { + return _contacts.map((e) => e.messageCache.size()).fold(0, (previousValue, element) => previousValue + element); + } } diff --git a/lib/models/messagecache.dart b/lib/models/messagecache.dart index 76c7aada..fbcfb60d 100644 --- a/lib/models/messagecache.dart +++ b/lib/models/messagecache.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:ffi'; import 'package:flutter/foundation.dart'; @@ -9,6 +10,11 @@ class MessageInfo { late String wrapper; MessageInfo(this.metadata, this.wrapper); + + int size() { + var wrapperSize = wrapper.length * 2; + return wrapperSize; + } } class LocalIndexMessage { @@ -155,4 +161,11 @@ class MessageCache extends ChangeNotifier { cache[messageID]?.metadata.error = true; notifyListeners(); } + + int size() { + // very naive cache size, assuming MessageInfo are fairly large on average + // and everything else is small in comparison + int cacheSize = cache.entries.map((e) => e.value.size()).fold(0, (previousValue, element) => previousValue! + element); + return cacheSize + cacheByHash.length * 64 + cacheByIndex.length * 16; + } } diff --git a/lib/models/profile.dart b/lib/models/profile.dart index 19df02d1..1848c2f9 100644 --- a/lib/models/profile.dart +++ b/lib/models/profile.dart @@ -339,4 +339,8 @@ class ProfileInfoState extends ChangeNotifier { _downloadTriggers[fileKey] = identifier; notifyListeners(); } + + int cacheMemUsage() { + return _contacts.cacheMemUsage(); + } } diff --git a/lib/models/profilelist.dart b/lib/models/profilelist.dart index 53a12384..bb3cd406 100644 --- a/lib/models/profilelist.dart +++ b/lib/models/profilelist.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/widgets.dart'; import 'profile.dart'; @@ -30,4 +31,8 @@ class ProfileListState extends ChangeNotifier { } int generateUnreadCount(String selectedProfile) => _profiles.where((p) => p.onion != selectedProfile).fold(0, (i, p) => i + p.unreadMessages); + + int cacheMemUsage() { + return _profiles.map((e) => e.cacheMemUsage()).fold(0, (previousValue, element) => previousValue + element); + } } diff --git a/lib/views/globalsettingsview.dart b/lib/views/globalsettingsview.dart index 75ad7187..e2a5cb99 100644 --- a/lib/views/globalsettingsview.dart +++ b/lib/views/globalsettingsview.dart @@ -46,7 +46,9 @@ class _GlobalSettingsViewState extends State { androidSettingsChangeChannel.setMethodCallHandler(handleSettingsChanged); if (Platform.isAndroid) { - isBatteryExempt().then((value) => setState(() { powerExempt = value; }) ); + isBatteryExempt().then((value) => setState(() { + powerExempt = value; + })); } else { powerExempt = false; } @@ -69,7 +71,6 @@ class _GlobalSettingsViewState extends State { return await androidSettingsChannel.invokeMethod('isBatteryExempt', {}) ?? false; } - Future requestBatteryExemption() async { await androidSettingsChannel.invokeMethod('requestBatteryExemption', {}); return Future.value(); @@ -217,26 +218,22 @@ class _GlobalSettingsViewState extends State { 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, style: TextStyle(color: settings - .current() - .mainTextColor)), - 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), - ), + child: SwitchListTile( + title: Text(AppLocalizations.of(context)!.settingAndroidPowerExemption, style: TextStyle(color: settings.current().mainTextColor)), + 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), @@ -464,6 +461,24 @@ class _GlobalSettingsViewState extends State { child: SelectableText(AppLocalizations.of(context)!.versionBuilddate.replaceAll("%1", EnvironmentConfig.BUILD_VER).replaceAll("%2", EnvironmentConfig.BUILD_DATE)), ) ]), + Visibility( + visible: EnvironmentConfig.BUILD_VER == dev_version && !Platform.isAndroid, + child: FutureBuilder( + future: 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(); + } + }, + ), + ) ])))); }); }); @@ -471,12 +486,11 @@ class _GlobalSettingsViewState extends State { showBatteryDialog(BuildContext context) { Widget okButton = ElevatedButton( - child: Text(AppLocalizations.of(context)!.okButton), - onPressed: () { - Navigator.of(context).pop(); - }, - ); - + child: Text(AppLocalizations.of(context)!.okButton), + onPressed: () { + Navigator.of(context).pop(); + }, + ); // set up the AlertDialog AlertDialog alert = AlertDialog(