mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-07-06 12:48:03 +02:00
feat: add device info to log export
- Add exportWithDeviceInfo() method to LogBuffer - Include app version, build number in export - Include device info: manufacturer, model, OS version, SDK level - Include log summary with counts by level - Update copy/share logs to use new method with device info
This commit is contained in:
@@ -65,21 +65,23 @@ class _LogScreenState extends State<LogScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
void _copyLogs() {
|
||||
final logs = LogBuffer().export();
|
||||
void _copyLogs() async {
|
||||
final logs = await LogBuffer().exportWithDeviceInfo();
|
||||
Clipboard.setData(ClipboardData(text: logs));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(context.l10n.logCopied),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(context.l10n.logCopied),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _shareLogs() {
|
||||
final logs = LogBuffer().export();
|
||||
void _shareLogs() async {
|
||||
final logs = await LogBuffer().exportWithDeviceInfo();
|
||||
SharePlus.instance.share(ShareParams(text: logs, subject: 'SpotiFLAC Logs'));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:logger/logger.dart';
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:spotiflac_android/constants/app_info.dart';
|
||||
import 'package:spotiflac_android/services/platform_bridge.dart';
|
||||
|
||||
class LogEntry {
|
||||
@@ -151,6 +154,97 @@ class LogBuffer extends ChangeNotifier {
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/// Export logs with device information for debugging
|
||||
Future<String> exportWithDeviceInfo() async {
|
||||
final buffer = StringBuffer();
|
||||
|
||||
buffer.writeln('=' * 60);
|
||||
buffer.writeln('SPOTIFLAC LOG EXPORT');
|
||||
buffer.writeln('=' * 60);
|
||||
buffer.writeln();
|
||||
|
||||
buffer.writeln('--- App Information ---');
|
||||
buffer.writeln('App Version: ${AppInfo.version} (Build ${AppInfo.buildNumber})');
|
||||
buffer.writeln('Generated: ${DateTime.now().toIso8601String()}');
|
||||
buffer.writeln();
|
||||
|
||||
buffer.writeln('--- Device Information ---');
|
||||
try {
|
||||
final deviceInfo = DeviceInfoPlugin();
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
final android = await deviceInfo.androidInfo;
|
||||
buffer.writeln('Platform: Android');
|
||||
buffer.writeln('Device: ${android.manufacturer} ${android.model}');
|
||||
buffer.writeln('Brand: ${android.brand}');
|
||||
buffer.writeln('Android Version: ${android.version.release} (SDK ${android.version.sdkInt})');
|
||||
buffer.writeln('Device ID: ${android.id}');
|
||||
buffer.writeln('Hardware: ${android.hardware}');
|
||||
buffer.writeln('Product: ${android.product}');
|
||||
buffer.writeln('Supported ABIs: ${android.supportedAbis.join(', ')}');
|
||||
buffer.writeln('Is Physical Device: ${android.isPhysicalDevice}');
|
||||
} else if (Platform.isIOS) {
|
||||
final ios = await deviceInfo.iosInfo;
|
||||
buffer.writeln('Platform: iOS');
|
||||
buffer.writeln('Device: ${ios.utsname.machine}');
|
||||
buffer.writeln('Model: ${ios.model}');
|
||||
buffer.writeln('System Name: ${ios.systemName}');
|
||||
buffer.writeln('System Version: ${ios.systemVersion}');
|
||||
buffer.writeln('Device Name: ${ios.name}');
|
||||
buffer.writeln('Is Physical Device: ${ios.isPhysicalDevice}');
|
||||
}
|
||||
} catch (e) {
|
||||
buffer.writeln('Failed to get device info: $e');
|
||||
}
|
||||
buffer.writeln();
|
||||
|
||||
buffer.writeln('--- Log Summary ---');
|
||||
buffer.writeln('Total Entries: ${_entries.length}');
|
||||
|
||||
int errorCount = 0;
|
||||
int warnCount = 0;
|
||||
int infoCount = 0;
|
||||
int debugCount = 0;
|
||||
int goCount = 0;
|
||||
|
||||
for (final entry in _entries) {
|
||||
switch (entry.level) {
|
||||
case 'ERROR':
|
||||
case 'FATAL':
|
||||
errorCount++;
|
||||
break;
|
||||
case 'WARN':
|
||||
warnCount++;
|
||||
break;
|
||||
case 'INFO':
|
||||
infoCount++;
|
||||
break;
|
||||
case 'DEBUG':
|
||||
debugCount++;
|
||||
break;
|
||||
}
|
||||
if (entry.isFromGo) goCount++;
|
||||
}
|
||||
|
||||
buffer.writeln('Errors: $errorCount');
|
||||
buffer.writeln('Warnings: $warnCount');
|
||||
buffer.writeln('Info: $infoCount');
|
||||
buffer.writeln('Debug: $debugCount');
|
||||
buffer.writeln('From Go Backend: $goCount');
|
||||
buffer.writeln();
|
||||
|
||||
buffer.writeln('=' * 60);
|
||||
buffer.writeln('LOG ENTRIES');
|
||||
buffer.writeln('=' * 60);
|
||||
buffer.writeln();
|
||||
|
||||
for (final entry in _entries) {
|
||||
buffer.writeln(entry.toString());
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
List<LogEntry> filter({String? level, String? tag, String? search}) {
|
||||
final tagLower = tag?.toLowerCase();
|
||||
final searchLower = search?.toLowerCase();
|
||||
|
||||
Reference in New Issue
Block a user