Send system info, closes #149

This commit is contained in:
franzap
2024-11-22 17:46:58 -03:00
parent b19f4290a6
commit 0edbf56fb4
5 changed files with 105 additions and 51 deletions
+2 -1
View File
@@ -115,7 +115,8 @@ mixin NostrAdapter<T extends DataModelMixin<T>> on Adapter<T> {
if (['apps', 'fileMetadatas'].contains(internalType)) {
if (Platform.isAndroid) {
final info = await ref.read(systemInfoProvider.future);
final info =
await ref.read(systemInfoNotifierProvider.notifier).fetch();
params['#f'] = info.androidInfo.supportedAbis.map((a) => 'android-$a');
}
}
+63 -28
View File
@@ -3,7 +3,6 @@ import 'dart:io';
import 'package:async_button_builder/async_button_builder.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_data/flutter_data.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_phoenix/flutter_phoenix.dart';
@@ -13,19 +12,20 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:intl/intl.dart';
import 'package:path_provider/path_provider.dart';
import 'package:zapstore/main.data.dart';
import 'package:zapstore/models/app.dart';
import 'package:zapstore/models/feedback.dart';
import 'package:zapstore/models/settings.dart';
import 'package:zapstore/utils/extensions.dart';
import 'package:zapstore/utils/system_info.dart';
import 'package:zapstore/widgets/app_drawer.dart';
import 'package:http/http.dart' as http;
class SettingsScreen extends HookConsumerWidget {
const SettingsScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final systemInfoState = ref.watch(systemInfoProvider);
final systemInfoState = ref.watch(systemInfoNotifierProvider);
final controller = useTextEditingController();
final user = ref.settings
.watchOne('_', alsoWatch: (_) => {_.user})
@@ -65,8 +65,22 @@ class SettingsScreen extends HookConsumerWidget {
final text =
'${controller.text.trim()} [from ${user.npub} on ${DateFormat('MMMM d, y').format(DateTime.now())}]';
final event = AppFeedback(content: text).sign(kI);
await ref.apps.nostrAdapter.relay.publish(event);
controller.clear();
try {
await http.post(Uri.parse('https://relay.zapstore.dev/'),
body: jsonEncode(event.toMap()),
headers: {'Content-Type': 'application/json'});
if (context.mounted) {
context.showInfo('Thank you',
description: 'Message sent successfully');
}
controller.clear();
} catch (e, stack) {
if (context.mounted) {
context.showError(
title: (e as dynamic).message ?? e.toString(),
description: stack.toString());
}
}
}
},
builder: (context, child, callback, state) {
@@ -123,18 +137,53 @@ class SettingsScreen extends HookConsumerWidget {
child: Text('Delete local cache'),
),
Gap(40),
Text(
'System information',
style: context.theme.textTheme.headlineLarge!
.copyWith(fontWeight: FontWeight.bold),
Row(
children: [
Text(
'System info',
style: context.theme.textTheme.headlineLarge!
.copyWith(fontWeight: FontWeight.bold),
),
Gap(20),
ElevatedButton(
onPressed: () {
ref.read(systemInfoNotifierProvider.notifier).fetch();
},
child: Text('Refresh'),
),
],
),
Gap(20),
GestureDetector(
onTap: () {
if (systemInfoState.hasValue) {
Clipboard.setData(
ClipboardData(text: systemInfoState.value!.toString()));
context.showInfo('Copied system information');
onLongPress: () async {
final info =
await ref.read(systemInfoNotifierProvider.notifier).fetch();
final dir = await getApplicationDocumentsDirectory();
final errors = jsonDecode(
await File('${dir.path}/errors.json').readAsString());
errors as Map<String, dynamic>;
errors['_'] = info.toString();
errors['_user'] =
ref.settings.findOneLocalById('_')!.user.value?.npub;
try {
await http.post(
Uri.parse('https://cdn.zapstore.dev/upload'),
body: utf8.encode(jsonEncode(errors)),
headers: {
'Content-Type': 'application/json',
'X-Filename': 'errors.json',
},
);
if (context.mounted) {
context.showInfo('System info sent',
description: 'Thank you');
}
} catch (e) {
if (context.mounted) {
context.showError(
title: 'Unable to send system info',
description: e.toString());
}
}
},
child: Text(switch (systemInfoState) {
@@ -142,20 +191,6 @@ class SettingsScreen extends HookConsumerWidget {
_ => '',
}),
),
HookBuilder(
builder: (context) {
final snapshot = useFuture(useMemoized(() async {
final dir = await getApplicationDocumentsDirectory();
return jsonDecode(
await File('${dir.path}/errors.json').readAsString());
}));
if (snapshot.hasData) {
return Text(
'Entries in errors.json: ${(snapshot.data as Map).length}');
}
return Container();
},
),
],
),
);
+36 -17
View File
@@ -10,28 +10,16 @@ import 'package:zapstore/utils/extensions.dart';
final deviceInfoPlugin = DeviceInfoPlugin();
final packageManager = AndroidPackageManager();
final systemInfoProvider = FutureProvider((ref) async {
final zsInfo =
await packageManager.getPackageInfo(packageName: kZapstoreAppIdentifier);
final dbInfo = {
'apps': ref.apps.countLocal,
'releases': ref.releases.countLocal,
'metadata': ref.fileMetadata.countLocal,
};
return SystemInfo(
androidInfo: await deviceInfoPlugin.androidInfo,
zsInfo: zsInfo!,
dbInfo: dbInfo,
);
});
class SystemInfo {
final AndroidDeviceInfo androidInfo;
final PackageInfo zsInfo;
final Map<String, int> dbInfo;
SystemInfo(
{required this.androidInfo, required this.zsInfo, required this.dbInfo});
SystemInfo({
required this.androidInfo,
required this.zsInfo,
required this.dbInfo,
});
@override
String toString() {
@@ -54,3 +42,34 @@ Low RAM device? ${androidInfo.isLowRamDevice}
''';
}
}
class SystemInfoNotifier extends StateNotifier<AsyncValue<SystemInfo>> {
final Ref ref;
SystemInfoNotifier(this.ref) : super(AsyncLoading()) {
fetch();
}
Future<SystemInfo> fetch() async {
final zsInfo = await packageManager.getPackageInfo(
packageName: kZapstoreAppIdentifier);
final dbInfo = {
'apps': ref.apps.countLocal,
'releases': ref.releases.countLocal,
'metadata': ref.fileMetadata.countLocal,
};
final info = SystemInfo(
androidInfo: await deviceInfoPlugin.androidInfo,
zsInfo: zsInfo!,
dbInfo: dbInfo,
);
state = AsyncData(info);
return info;
}
}
final systemInfoNotifierProvider =
StateNotifierProvider<SystemInfoNotifier, AsyncValue<SystemInfo>>(
SystemInfoNotifier.new);
+1 -1
View File
@@ -20,7 +20,7 @@ class DrawerContainer extends StatelessWidget {
Expanded(child: LoginContainer()),
Consumer(
builder: (context, ref, _) {
final state = ref.watch(systemInfoProvider);
final state = ref.watch(systemInfoNotifierProvider);
return switch (state) {
AsyncData(:final value) => Text(
'Version: ${value.zsInfo.versionName} (${value.zsInfo.versionCode}, $kDbVersion)',
+3 -4
View File
@@ -139,7 +139,8 @@ Widget materialErrorBuilder(BuildContext context, Widget? widget) {
Future<void> _sendErrorReport(
WidgetRef ref, Object exception, StackTrace? stack) async {
final systemInfo = await ref.read(systemInfoProvider.future);
final systemInfo =
await ref.read(systemInfoNotifierProvider.notifier).fetch();
var map = {
'e': exception.toString(),
@@ -147,10 +148,8 @@ Future<void> _sendErrorReport(
'info': systemInfo.androidInfo.toString()
};
final client = http.Client();
final event = AppFeedback(content: jsonEncode(map)).sign(kI);
await client.post(Uri.parse('https://relay.zapstore.dev/'),
await http.post(Uri.parse('https://relay.zapstore.dev/'),
body: jsonEncode(event.toMap()),
headers: {'Content-Type': 'application/json'});
client.close();
}