Skip to content

Commit d7ccdb0

Browse files
committed
Added dialog to upload logs window
1 parent 22334a4 commit d7ccdb0

File tree

3 files changed

+844
-129
lines changed

3 files changed

+844
-129
lines changed

.build_version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.1.0
1+
1.1.1

lib/screens/settings_screen.dart

Lines changed: 18 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ import '../utils/debug_logger_io.dart';
2020
import '../utils/distance_formatter.dart';
2121
import '../models/user_preferences.dart';
2222
import '../services/debug_file_logger.dart';
23-
import '../services/debug_submit_service.dart';
2423
import '../services/gps_simulator_service.dart';
2524
import '../services/offline_session_service.dart';
2625
import '../services/permission_disclosure_service.dart';
2726
import '../utils/constants.dart';
2827
import '../widgets/bug_report_dialog.dart';
28+
import '../widgets/upload_logs_dialog.dart';
2929
import 'package:intl/intl.dart';
3030
import '../widgets/app_toast.dart';
3131

@@ -42,93 +42,19 @@ class _SettingsScreenState extends State<SettingsScreen> {
4242
int _versionTapCount = 0;
4343
DateTime? _lastVersionTap;
4444

45-
// Debug log upload tracking
46-
String? _uploadingFilePath;
47-
final Set<String> _uploadedFiles = {};
45+
Future<void> _showUploadLogsDialog(BuildContext context, AppStateProvider appState) async {
46+
final result = await showUploadLogsDialog(context, appState);
4847

49-
Future<void> _uploadSingleLogFile(AppStateProvider appState, File file) async {
50-
final filename = file.path.split('/').last;
51-
52-
setState(() {
53-
_uploadingFilePath = file.path;
54-
});
55-
56-
try {
57-
final service = DebugSubmitService();
58-
59-
// Use persistent device info
60-
final publicKey = appState.devicePublicKey ??
61-
appState.lastConnectedPublicKey ??
62-
'not-connected';
63-
final deviceName = appState.lastConnectedDeviceName ?? 'not-connected';
64-
65-
final success = await service.uploadDebugFileOnly(
66-
file: file,
67-
deviceId: deviceName,
68-
publicKey: publicKey,
69-
appVersion: AppConstants.appVersion,
70-
devicePlatform: DebugSubmitService.getDevicePlatform(),
71-
userNotes: 'Direct debug log upload from $deviceName',
72-
);
73-
74-
service.dispose();
75-
76-
if (!mounted) return;
77-
78-
if (success) {
79-
setState(() {
80-
_uploadedFiles.add(file.path);
81-
_uploadingFilePath = null;
82-
});
83-
AppToast.success(context, 'Uploaded $filename');
84-
} else {
85-
setState(() {
86-
_uploadingFilePath = null;
87-
});
88-
AppToast.error(context, 'Failed to upload $filename');
89-
}
90-
} catch (e) {
91-
debugError('[SETTINGS] Log file upload error: $e');
92-
if (mounted) {
93-
setState(() {
94-
_uploadingFilePath = null;
95-
});
96-
AppToast.error(context, 'Upload error: $e');
97-
}
98-
}
99-
}
100-
101-
/// Upload the current (active) log file by rotating it first
102-
Future<void> _uploadCurrentLogFile(AppStateProvider appState, File currentFile) async {
103-
final originalPath = currentFile.path;
104-
105-
setState(() {
106-
_uploadingFilePath = originalPath;
107-
});
108-
109-
try {
110-
// Rotate the log: closes current file, starts a new one
111-
// The original file is now closed and safe to upload
112-
await appState.prepareDebugLogsForUpload();
113-
114-
if (!mounted) return;
115-
116-
// The original file still exists at the same path, now closed
117-
final closedFile = File(originalPath);
118-
if (!closedFile.existsSync()) {
119-
throw Exception('Log file not found after rotation');
120-
}
48+
if (!context.mounted || result == null) return;
12149

122-
// Now upload the closed file
123-
await _uploadSingleLogFile(appState, closedFile);
124-
} catch (e) {
125-
debugError('[SETTINGS] Current log upload error: $e');
126-
if (mounted) {
127-
setState(() {
128-
_uploadingFilePath = null;
129-
});
130-
AppToast.error(context, 'Upload error: $e');
50+
if (result.success) {
51+
String message = 'Uploaded ${result.uploadedCount} log file${result.uploadedCount == 1 ? '' : 's'}';
52+
if (result.failedCount > 0) {
53+
message += ' (${result.failedCount} failed)';
13154
}
55+
AppToast.success(context, message);
56+
} else if (result.errorMessage != null) {
57+
AppToast.error(context, result.errorMessage!);
13258
}
13359
}
13460

@@ -716,12 +642,18 @@ class _SettingsScreenState extends State<SettingsScreen> {
716642
),
717643
),
718644
const Spacer(),
719-
if (appState.debugLogFiles.isNotEmpty)
645+
if (appState.debugLogFiles.isNotEmpty) ...[
646+
TextButton.icon(
647+
icon: const Icon(Icons.cloud_upload, size: 18),
648+
label: const Text('Upload'),
649+
onPressed: () => _showUploadLogsDialog(context, appState),
650+
),
720651
TextButton.icon(
721652
icon: const Icon(Icons.delete_sweep, size: 18),
722653
label: const Text('Delete All'),
723654
onPressed: () => _confirmDeleteAllLogs(context, appState),
724655
),
656+
],
725657
],
726658
),
727659
),
@@ -741,18 +673,13 @@ class _SettingsScreenState extends State<SettingsScreen> {
741673
final file = entry.value;
742674
final filename = file.path.split('/').last;
743675
final sizeBytes = file.lengthSync();
744-
final isUploading = _uploadingFilePath == file.path;
745-
final wasUploaded = _uploadedFiles.contains(file.path);
746-
// First file (index 0) is the most recent/active log - can't upload
747676
final isCurrentLog = index == 0;
748-
// Parse unix timestamp from filename (meshmapper-debug-{timestamp}.txt)
749677
final timestampMatch = RegExp(r'meshmapper-debug-(\d+)\.txt').firstMatch(filename);
750678
final fileDate = timestampMatch != null
751679
? DateTime.fromMillisecondsSinceEpoch(int.parse(timestampMatch.group(1)!) * 1000)
752680
: null;
753681
final dateStr = fileDate != null ? DateFormat('MMM d, h:mm a').format(fileDate) : filename;
754682

755-
// Format size and show part count for oversized files
756683
String sizeDisplay;
757684
final partCount = DebugFileLogger.estimatePartCount(sizeBytes);
758685
if (sizeBytes >= DebugFileLogger.maxUploadSizeBytes) {
@@ -775,48 +702,11 @@ class _SettingsScreenState extends State<SettingsScreen> {
775702
trailing: Row(
776703
mainAxisSize: MainAxisSize.min,
777704
children: [
778-
// Upload button
779-
if (wasUploaded)
780-
Container(
781-
width: 40,
782-
height: 40,
783-
alignment: Alignment.center,
784-
child: const Icon(
785-
Icons.check_circle,
786-
size: 20,
787-
color: Colors.green,
788-
),
789-
)
790-
else if (isUploading)
791-
Container(
792-
width: 40,
793-
height: 40,
794-
alignment: Alignment.center,
795-
child: const SizedBox(
796-
width: 20,
797-
height: 20,
798-
child: CircularProgressIndicator(strokeWidth: 2),
799-
),
800-
)
801-
else
802-
IconButton(
803-
icon: const Icon(Icons.cloud_upload, size: 20),
804-
onPressed: _uploadingFilePath != null
805-
? null
806-
: () => isCurrentLog
807-
? _uploadCurrentLogFile(appState, file)
808-
: _uploadSingleLogFile(appState, file),
809-
tooltip: isCurrentLog
810-
? 'Close log and upload'
811-
: 'Upload to developer',
812-
),
813-
// View button
814705
IconButton(
815706
icon: const Icon(Icons.visibility, size: 20),
816707
onPressed: () => _showLogViewer(context, appState, file),
817708
tooltip: 'View',
818709
),
819-
// Share button
820710
IconButton(
821711
icon: const Icon(Icons.share, size: 20),
822712
onPressed: () => appState.shareDebugLog(file),

0 commit comments

Comments
 (0)