From d4cd0967a39487d86fe2fd009a5fad25bef36d0e Mon Sep 17 00:00:00 2001 From: franzap <_@franzap.com> Date: Sun, 16 Jun 2024 21:18:23 -0300 Subject: [PATCH] Add system information to settings screen --- lib/models/app.dart | 10 ++----- lib/screens/app_detail_screen.dart | 19 ++++--------- lib/screens/settings_screen.dart | 23 ++++++++++++++++ lib/utils/system_info.dart | 43 ++++++++++++++++++++++++++++++ pubspec.lock | 32 ++++++++++++++++------ pubspec.yaml | 3 ++- 6 files changed, 99 insertions(+), 31 deletions(-) create mode 100644 lib/utils/system_info.dart diff --git a/lib/models/app.dart b/lib/models/app.dart index 6f1dd80..8921813 100644 --- a/lib/models/app.dart +++ b/lib/models/app.dart @@ -20,6 +20,7 @@ import 'package:zapstore/models/user.dart'; import 'package:http/http.dart' as http; import 'package:path/path.dart' as path; import 'package:zapstore/screens/search_screen.dart'; +import 'package:zapstore/utils/system_info.dart'; part 'app.g.dart'; @@ -45,10 +46,6 @@ class App extends BaseApp with DataModelMixin { DataModel.adapterFor(this).ref.read(installedAppProvider)[id!.toString()]; FileMetadata? get latestMetadata { - // if (Platform.isAndroid) { - // final androidInfo = await deviceInfo.androidInfo; - // return androidInfo.architecture; // e.g. "arm64-v8a" - // } return releases.ordered.firstOrNull?.artifacts .where((a) => a.mimeType == 'application/vnd.android.package-archive' && @@ -260,13 +257,10 @@ mixin AppAdapter on Adapter { return apps.first; } - static AndroidPackageManager? _packageManager; - Future> getInstalledAppsMap({bool defer = false}) async { late List? infos; if (Platform.isAndroid) { - _packageManager ??= AndroidPackageManager(); - infos = await _packageManager!.getInstalledPackages(); + infos = await packageManager.getInstalledPackages(); } else { infos = []; } diff --git a/lib/screens/app_detail_screen.dart b/lib/screens/app_detail_screen.dart index 3287494..ba2a784 100644 --- a/lib/screens/app_detail_screen.dart +++ b/lib/screens/app_detail_screen.dart @@ -1,7 +1,6 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:collection/collection.dart'; -import 'package:external_app_launcher/external_app_launcher.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -10,7 +9,6 @@ import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:intl/intl.dart'; import 'package:percent_indicator/linear_percent_indicator.dart'; -import 'package:toastification/toastification.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:zapstore/main.data.dart'; import 'package:zapstore/models/app.dart'; @@ -18,6 +16,7 @@ import 'package:zapstore/models/release.dart'; import 'package:zapstore/models/settings.dart'; import 'package:zapstore/models/user.dart'; import 'package:zapstore/utils/extensions.dart'; +import 'package:zapstore/utils/system_info.dart'; import 'package:zapstore/widgets/app_drawer.dart'; import 'package:zapstore/widgets/author_container.dart'; import 'package:zapstore/widgets/pill_widget.dart'; @@ -51,15 +50,6 @@ class AppDetailScreen extends HookConsumerWidget { Expanded( child: CustomScrollView( slivers: [ - // SliverAppBar( - // pinned: true, - // leading: IconButton( - // icon: Icon(Icons.arrow_back), - // onPressed: () { - // context.pop(); - // }, - // ), - // ), SliverList( delegate: SliverChildListDelegate( [ @@ -472,7 +462,7 @@ class InstallButton extends ConsumerWidget { AppInstallStatus.differentArchitecture => null, AppInstallStatus.downgrade => null, AppInstallStatus.updated => () { - LaunchApp.openApp(androidPackageName: app.id!.toString()); + packageManager.openApp(app.id!.toString()); }, _ => switch (progress) { IdleInstallProgress() => () { @@ -532,8 +522,9 @@ class InstallButton extends ConsumerWidget { _ => switch (progress) { IdleInstallProgress() => app.canUpdate ? AutoSizeText( - 'Update ${compact ? '' : 'to ${app.latestMetadata!.version!}'}', - maxLines: 1) + 'Update${compact ? '' : ' to ${app.latestMetadata!.version!}'}', + maxLines: 1, + ) : Text('Install'), DownloadingInstallProgress(:final progress) => Text( '${(progress * 100).floor()}%', diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 9ef8b10..c684cfb 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -1,5 +1,6 @@ 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'; @@ -12,6 +13,7 @@ import 'package:zapstore/main.data.dart'; import 'package:zapstore/models/app.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'; class SettingsScreen extends HookConsumerWidget { @@ -19,6 +21,7 @@ class SettingsScreen extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final systemInfoState = ref.watch(systemInfoProvider); final controller = useTextEditingController(); final user = ref.settings .watchOne('_', alsoWatch: (_) => {_.user}) @@ -112,6 +115,26 @@ class SettingsScreen extends HookConsumerWidget { }, child: Text('Delete local cache'), ), + Gap(40), + Text( + 'System information', + style: context.theme.textTheme.headlineLarge! + .copyWith(fontWeight: FontWeight.bold), + ), + Gap(20), + GestureDetector( + onTap: () { + if (systemInfoState.hasValue) { + Clipboard.setData( + ClipboardData(text: systemInfoState.value!.toString())); + context.showInfo('Copied system information'); + } + }, + child: Text(switch (systemInfoState) { + AsyncData(:final value) => value.toString(), + _ => '', + }), + ), ], ), ); diff --git a/lib/utils/system_info.dart b/lib/utils/system_info.dart new file mode 100644 index 0000000..aeb20b9 --- /dev/null +++ b/lib/utils/system_info.dart @@ -0,0 +1,43 @@ +import 'package:android_package_manager/android_package_manager.dart'; +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:system_info2/system_info2.dart'; +import 'package:zapstore/main.dart'; + +final deviceInfoPlugin = DeviceInfoPlugin(); +final packageManager = AndroidPackageManager(); + +final systemInfoProvider = FutureProvider((ref) async { + final zsInfo = + await packageManager.getPackageInfo(packageName: 'store.zap.app'); + return SystemInfo( + androidInfo: await deviceInfoPlugin.androidInfo, + zsInfo: zsInfo!, + ); +}); + +class SystemInfo { + final AndroidDeviceInfo androidInfo; + final PackageInfo zsInfo; + + SystemInfo({required this.androidInfo, required this.zsInfo}); + + @override + String toString() { + return ''' +Version name: ${zsInfo.versionName} +Version code: ${zsInfo.versionCode} +DB version: $kDbVersion +SDK version: ${androidInfo.version.sdkInt} +Device: ${androidInfo.brand} ${androidInfo.device} (${androidInfo.hardware}) +Display: ${androidInfo.display} +Model: ${androidInfo.manufacturer} ${androidInfo.model} ${androidInfo.product} +Host: ${androidInfo.host} +Supported ABIs: ${androidInfo.supported64BitAbis} + +Free/total memory: ${SysInfo.getFreePhysicalMemory() ~/ (1024 * 1024)}/${SysInfo.getTotalPhysicalMemory() ~/ (1024 * 1024)} MB +Free/total virtual: ${SysInfo.getFreeVirtualMemory() ~/ (1024 * 1024)}/${SysInfo.getTotalVirtualMemory() ~/ (1024 * 1024)} MB +Low RAM device? ${androidInfo.isLowRamDevice} +'''; + } +} diff --git a/pubspec.lock b/pubspec.lock index c0b9496..fea1c92 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -65,6 +65,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" + basic_utils: + dependency: "direct main" + description: + name: basic_utils + sha256: "2064b21d3c41ed7654bc82cc476fd65542e04d60059b74d5eed490a4da08fc6c" + url: "https://pub.dev" + source: hosted + version: "5.7.0" bech32: dependency: transitive description: @@ -297,14 +305,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.5" - external_app_launcher: - dependency: "direct main" - description: - name: external_app_launcher - sha256: a80847a8e24cce37f1c953ec20a9600c3b12167e279b5868945e880cea717bf7 - url: "https://pub.dev" - source: hosted - version: "4.0.0" fake_async: dependency: transitive description: @@ -455,6 +455,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + globbing: + dependency: transitive + description: + name: globbing + sha256: "4f89cfaf6fa74c9c1740a96259da06bd45411ede56744e28017cc534a12b6e2d" + url: "https://pub.dev" + source: hosted + version: "1.0.0" go_router: dependency: "direct main" description: @@ -1035,6 +1043,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.0+1" + system_info2: + dependency: "direct main" + description: + name: system_info2 + sha256: "65206bbef475217008b5827374767550a5420ce70a04d2d7e94d1d2253f3efc9" + url: "https://pub.dev" + source: hosted + version: "4.0.0" term_glyph: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index dd09bca..82d4b87 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,13 +35,14 @@ dependencies: auto_size_text: ^3.0.0 intl: ^0.18.1 device_info_plus: ^10.1.0 - external_app_launcher: ^4.0.0 install_plugin: ^2.1.0 flutter_layout_grid: ^2.0.6 skeletonizer: ^1.1.2+1 flutter_phoenix: ^1.1.1 percent_indicator: ^4.2.3 toastification: ^2.0.0 + system_info2: ^4.0.0 + basic_utils: ^5.7.0 dependency_overrides: purplebase: