diff --git a/firka/lib/helpers/settings/setting.dart b/firka/lib/helpers/settings/setting.dart index 3c84f390..8119b5b2 100644 --- a/firka/lib/helpers/settings/setting.dart +++ b/firka/lib/helpers/settings/setting.dart @@ -285,6 +285,7 @@ class SettingsStore { l10n.s_stats_for_nerds, false, always), + "logs": SettingsLogs(0, always), }), isDeveloper), @@ -723,6 +724,29 @@ class SettingsKretenAccountPicker implements SettingsItem { } } +class SettingsLogs implements SettingsItem { + @override + Id key; + @override + FirkaIconType? iconType; + @override + Object? iconData; + @override + bool Function() visibilityProvider; + @override + Future Function() postUpdate = () async {}; + String title = ""; + String icon = ""; + + SettingsLogs(this.key, this.visibilityProvider); + + @override + Future load(IsarCollection model) async {} + + @override + Future save(IsarCollection model) async {} +} + class SettingsAppIconPicker implements SettingsItem { @override Id key; diff --git a/firka/lib/main.dart b/firka/lib/main.dart index 8ff19f41..8af5adc3 100644 --- a/firka/lib/main.dart +++ b/firka/lib/main.dart @@ -64,6 +64,7 @@ class DeviceInfo { class AppInitialization { final Isar isar; + final Directory appDir; final PackageInfo packageInfo; final DeviceInfo devInfo; late KretaClient client; @@ -76,6 +77,7 @@ class AppInitialization { AppInitialization({ required this.isar, + required this.appDir, required this.devInfo, required this.packageInfo, required this.tokens, @@ -229,6 +231,7 @@ Future initializeApp() async { var init = AppInitialization( isar: isar, + appDir: await getApplicationDocumentsDirectory(), devInfo: devInfo, packageInfo: await PackageInfo.fromPlatform(), tokens: tokens, diff --git a/firka/lib/ui/phone/screens/settings/settings_screen.dart b/firka/lib/ui/phone/screens/settings/settings_screen.dart index b040c6c9..ae32b2f9 100644 --- a/firka/lib/ui/phone/screens/settings/settings_screen.dart +++ b/firka/lib/ui/phone/screens/settings/settings_screen.dart @@ -1,4 +1,5 @@ import 'dart:collection'; +import 'dart:io'; import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart'; import 'package:firka/helpers/db/models/app_settings_model.dart'; @@ -11,6 +12,8 @@ import 'package:firka/ui/widget/firka_icon.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:majesticons_flutter/majesticons_flutter.dart'; +import 'package:path/path.dart' as p; +import 'package:share_plus/share_plus.dart'; import '../../../../helpers/firka_bundle.dart'; import '../../../../helpers/firka_state.dart'; @@ -576,6 +579,76 @@ class _SettingsScreenState extends FirkaState { )); continue; } + if (item is SettingsLogs) { + final logFileRegex = RegExp(r'^(\d{4})_(\d{2})_(\d{2})\.log$'); + + for (final entity in widget.data.appDir.listSync()) { + if (entity is! File) continue; + final name = entity.uri.pathSegments.last; + final m = logFileRegex.firstMatch(name); + if (m == null) continue; + + widgets.add(GestureDetector( + child: SizedBox( + height: 52, + child: FirkaCard( + left: [ + FirkaIconWidget( + FirkaIconType.majesticons, + Majesticon.noteTextSolid, + color: appStyle.colors.accent, + ), + Text( + name, + style: appStyle.fonts.B_16R + .apply(color: appStyle.colors.textPrimary), + ), + ], + ), + ), + onTap: () async { + try { + logger.info("Compressing log file: ${entity.path}"); + final original = File(entity.path); + final originalBytes = await original.readAsBytes(); + final gzBytes = GZipCodec().encode(originalBytes); + final tempDir = await Directory.systemTemp.createTemp('firka'); + final gzPath = + p.join(tempDir.path, '${p.basename(entity.path)}.gz'); + final gzFile = + await File(gzPath).writeAsBytes(gzBytes, flush: true); + + final params = ShareParams( + text: name, + files: [XFile(gzFile.path, mimeType: 'application/gzip')], + ); + + await SharePlus.instance.share(params); + + await gzFile.delete(); + await tempDir.delete(); + } catch (ex) { + if (ex is Error) { + logger.shout("Failed to compress log file", ex.toString(), + ex.stackTrace); + } else { + logger.shout("Failed to compress log file", ex.toString()); + } + + logger.info("Sharing regular log file instead: ${entity.path}"); + final params = ShareParams( + text: name, + files: [XFile(entity.path, mimeType: 'text/plain')], + ); + + await SharePlus.instance.share(params); + } + }, + )); + widgets.add(SizedBox(height: 8)); + } + continue; + } } return widgets; diff --git a/firka/pubspec.yaml b/firka/pubspec.yaml index 38e7fc99..7a5c8061 100644 --- a/firka/pubspec.yaml +++ b/firka/pubspec.yaml @@ -67,6 +67,7 @@ dependencies: smart_scroll: ^1.0.0 live_activities: ^2.4.1 logging: ^1.3.0 + share_plus: ^11.1.0 dev_dependencies: flutter_test: