Debug Info Pane for Desktop
continuous-integration/drone/pr Build is passing Details

This commit is contained in:
Sarah Jamie Lewis 2022-04-14 15:34:17 -07:00
parent 548e7f4925
commit 1df348c0c1
10 changed files with 92 additions and 30 deletions

View File

@ -1 +1 @@
2022-04-04-17-46-v1.6.0-15-g97defdf
2022-04-14-18-14-v.1.7.0-2-g9901e08

View File

@ -1 +1 @@
2022-04-04-21-46-v1.6.0-15-g97defdf
2022-04-14-22-15-v.1.7.0-2-g9901e08

View File

@ -118,4 +118,6 @@ abstract class Cwtch {
void l10nInit(String notificationSimple, String notificationConversationInfo);
void dispose();
Future<dynamic> GetDebugInfo();
}

View File

@ -102,6 +102,9 @@ typedef VoidFromStringIntIntFn = void Function(Pointer<Utf8>, int, int, int);
typedef appbus_events_function = Pointer<Utf8> Function();
typedef AppbusEventsFn = Pointer<Utf8> Function();
typedef void_to_string = Pointer<Utf8> Function();
typedef StringFromVoid = Pointer<Utf8> 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<String> GetDebugInfo() async {
var getDebugInfo = library.lookup<NativeFunction<void_to_string>>("c_GetDebugInfo");
final GetDebugInfo = getDebugInfo.asFunction<StringFromVoid>();
Pointer<Utf8> result = GetDebugInfo();
String debugResult = result.toDartString();
_UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(result);
return debugResult;
}
}

View File

@ -326,4 +326,11 @@ class CwtchGomobile implements Cwtch {
Future<dynamic> 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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -339,4 +339,8 @@ class ProfileInfoState extends ChangeNotifier {
_downloadTriggers[fileKey] = identifier;
notifyListeners();
}
int cacheMemUsage() {
return _contacts.cacheMemUsage();
}
}

View File

@ -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);
}
}

View File

@ -46,7 +46,9 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
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<GlobalSettingsView> {
return await androidSettingsChannel.invokeMethod('isBatteryExempt', {}) ?? false;
}
Future<void> requestBatteryExemption() async {
await androidSettingsChannel.invokeMethod('requestBatteryExemption', {});
return Future.value();
@ -217,26 +218,22 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
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<GlobalSettingsView> {
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<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();
}
},
),
)
]))));
});
});
@ -471,12 +486,11 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
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(