Skip to content

Conversation

@BraCR10
Copy link
Member

@BraCR10 BraCR10 commented Jan 20, 2026

Phase 5: File Export & Persistence

This PR implements manual log export functionality with a menu UI.

What's Included

Export Service:

  • New LoggerExportService for saving and sharing logs
    • Generate timestamped .txt files
    • Export using FilePicker
    • Share via native system share sheet

UI Updates:

  • Menu (⋮) in logs screen with 3 actions: Save, Share, Clear
  • Clean success messages without file paths
  • Menu items disabled when no logs available

Testing

Navigate to: Settings → Dev Tools → Logs Report

  1. Enable logging and generate some logs
  2. Tap the 3-dot menu (⋮) in the AppBar
  3. Save: Choose location and verify file saved
  4. Share: Test sharing via different apps
  5. Clear: Verify confirmation dialog works

See docs/LOGGING_IMPLEMENTATION.md for details.

Summary by CodeRabbit

  • New Features

    • Added a logs actions menu to save, share, or clear logs (clear requires confirmation).
    • Manual export via menu: choose folder to save a formatted .txt and share via system share sheet.
  • Behavior Change

    • Removed automatic export/persistence and restore on restart; logging is now manually exported.
  • Localization

    • Added English, Spanish, and Italian strings for log/export UI.
  • Documentation

    • Updated logging implementation docs.

✏️ Tip: You can customize this high-level summary in your review settings.

BraCR10 and others added 30 commits January 7, 2026 13:00
Create LoggerExportService with methods to:
- Generate timestamped filenames (mostro_logs_YYYY-MM-DD_HH-MM-SS.txt)
- Convert LogEntry list to formatted text with metadata header
- Export logs using FilePicker.saveFile() for Android 13+ SAF compatibility
- Export logs to temp directory for sharing
- Share logs via native share sheet using Share.shareXFiles()
Create LogsActionsMenu with PopupMenuButton containing three actions:
- Save: Export logs to user-selected location via FilePicker
- Share: Share logs via native system share sheet
- Clear: Delete all logs with confirmation dialog

Features:
- Uses HeroIcons for consistent iconography
- Menu items disabled when no logs available
- Proper error handling with SnackBar feedback
- Success message without showing file path for cleaner UX
Replace individual IconButtons with LogsActionsMenu in AppBar.
Remove methods moved to menu widget.
Clean up lifecycle observer.
Simplified scope: manual save only when user explicitly requests it.
Clean up Settings model by removing logExportPath field and related code.
Simplified implementation: no default folder configuration.
Add translations in all languages (EN, ES, IT) for:
- saveLogs, logsExportSuccess, logsExportError
- shareLogsError, shareLogs
- exportSettings, close

Simplified success message without showing file path.
Mark Phase 5 as completed with implemented features:
- Manual export via hamburger menu
- Save logs to user-selected location using FilePicker
- Share logs via native system share sheet
- Generate timestamped .txt files
- Clear logs with confirmation dialog
- Simplified scope: manual save only, no auto-save or default folder
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 20, 2026

Walkthrough

Replaces automatic log persistence with manual export/share/clear. Adds LoggerExportService to format/save/share logs, a LogsActionsMenu UI exposing Save/Share/Clear, replaces the appbar clear button, updates lifecycle observer hooks, and adds localization and docs entries for the new flow. Phase bumped to 6.

Changes

Cohort / File(s) Summary
Documentation
docs/LOGGING_IMPLEMENTATION.md
Phase bumped to 6; removed auto-export/persistence entries; documents manual export via menu, FilePicker save, native share, and clear-with-confirmation.
Logs Screen UI
lib/features/logs/screens/logs_screen.dart
Replaced appbar delete icon with LogsActionsMenu(); registers WidgetsBindingObserver in state; removed inline clear-confirmation flow and its handler.
Logs Actions Menu Widget
lib/features/logs/widgets/logs_actions_menu.dart
New LogsActionsMenu (ConsumerWidget) providing Save/Share/Clear popup actions, confirmation dialog for clear, SnackBar feedback, and delegates export/share to LoggerExportService.
Logger Export Service
lib/services/logger_export_service.dart
New LoggerExportService and LogExportStrings: filename generation, log -> text formatting, exportLogsToFolder(), exportLogsForSharing(), and shareLogs() using FilePicker, temp files, and share_plus.
Localization
lib/l10n/intl_en.arb, lib/l10n/intl_es.arb, lib/l10n/intl_it.arb
Added keys for export/share UI and messages: saveLogs, logsExportSuccess, logsExportError, shareLogsError, exportSettings, logsHeaderTitle, logsGeneratedLabel, logsTotalLabel, logsShareSubject, logsShareText.
Settings
lib/features/settings/settings.dart
Removed two inline comments on public fields only; no behavioral changes.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant LogsActionsMenu
    participant LoggerExportService
    participant FilePicker
    participant FileSystem
    participant SnackBar

    User->>LogsActionsMenu: Tap "Save Logs"
    LogsActionsMenu->>LoggerExportService: exportLogsToFolder(logs, strings)
    LoggerExportService->>LoggerExportService: _generateFilename() and _logsToText(logs)
    LoggerExportService->>FilePicker: prompt save location
    FilePicker->>User: show file picker
    User->>FilePicker: selects destination
    FilePicker->>FileSystem: write UTF-8 bytes to chosen path
    FileSystem-->>LoggerExportService: return saved path
    LoggerExportService-->>LogsActionsMenu: return path/null
    LogsActionsMenu->>SnackBar: show success or error message
Loading
sequenceDiagram
    participant User
    participant LogsActionsMenu
    participant LoggerExportService
    participant TempFS
    participant SharePlugin
    participant NativeShare

    User->>LogsActionsMenu: Tap "Share Logs"
    LogsActionsMenu->>LoggerExportService: exportLogsForSharing(logs, strings)
    LoggerExportService->>LoggerExportService: _logsToText(logs)
    LoggerExportService->>TempFS: write temp file
    TempFS-->>LoggerExportService: return temp file
    LoggerExportService->>SharePlugin: shareLogs(file, subject, text)
    SharePlugin->>NativeShare: invoke native share sheet
    NativeShare-->>User: display share options
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • grunch
  • AndreaDiazCorreia
  • Catrya

Poem

🐇 I hopped through lines both short and long,
I bundled traces into one little song.
Tap the menu, save or share with cheer,
A temp file, a picker—logs held near.
Carrots for devs who made this clear.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding functionality to share and save log files, which aligns with the primary objective of Phase 5 implementation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In `@lib/features/logs/widgets/logs_actions_menu.dart`:
- Around line 121-129: In the catch block in logs_actions_menu.dart where
ScaffoldMessenger.of(context).showSnackBar is used, stop interpolating the raw
exception ($e) into the SnackBar content; instead display a generic localized
message (use S.of(context)!.logsExportError or add a new localized key like
logsExportErrorGeneric) and keep the full error/stackTrace passed to
_logger.e('_logger.e(...)') for debugging; update both the catch block shown and
the similar handler around the other occurrence (the second SnackBar at 138-145)
so no raw exception text is shown to users while preserving logging.

In `@lib/l10n/intl_en.arb`:
- Around line 1296-1303: The ARB contains duplicate keys "shareLogs" and "close"
which will break parsing; remove the duplicated entries from this block (or
rename them to unique keys if these strings must be distinct), ensuring only one
definition of "shareLogs" and "close" remains in the intl_en.arb file and update
any callers to use the new key name if you choose to rename.

In `@lib/l10n/intl_es.arb`:
- Around line 1272-1279: The ARB snippet contains duplicate localization keys
"shareLogs" and "close" which will break gen_l10n; remove the duplicate entries
from this block in lib/l10n/intl_es.arb (or rename them if these strings must be
distinct) and ensure only a single definition of "shareLogs" and "close"
remains; update any callers only if you rename the keys so code references the
new key names consistently.

In `@lib/l10n/intl_it.arb`:
- Around line 1327-1334: Remove the duplicate ARB keys causing parse/generation
failures by locating the repeated keys "shareLogs" and "close" in the current
diff (they are redefined alongside "viewAndExportLogs", "saveLogs", etc.) and
either delete these duplicate entries or rename them to a unique key if a
different label is intended; ensure only one definition of "shareLogs" and one
of "close" remain in the ARB file and run the intl generation to confirm the
error is resolved.

In `@lib/services/logger_export_service.dart`:
- Around line 19-25: Add the specified localization keys to the ARB files:
logsHeaderTitle, logsGeneratedLabel, logsTotalLabel, logsShareSubject,
logsShareText, and logsEmptyMessage (map to existing noLogsAvailable if
present). In lib/services/logger_export_service.dart, modify the
LoggerExportService export methods (e.g., the method that builds the export
string / share payload) to accept these localized string parameters:
logsHeaderTitle, logsGeneratedLabel, logsTotalLabel, logsShareSubject,
logsShareText, and logsEmptyMessage; replace hard-coded literals ('Mostro P2P
Application Logs', 'Generated', 'Total logs', 'Mostro P2P Logs', 'Application
logs from Mostro P2P', 'No logs available') with the passed parameters (use
logsEmptyMessage for the empty-case return), and update callers (the Widget with
BuildContext) to pass S.of(context).logsHeaderTitle etc. when invoking the
service.
🧹 Nitpick comments (2)
lib/features/logs/widgets/logs_actions_menu.dart (1)

11-15: Make the widget const by hoisting the logger to a static field.

This improves immutability and avoids rebuilding a new Logger for each widget instance.
As per coding guidelines, prefer const constructors where possible.

♻️ Proposed change
 class LogsActionsMenu extends ConsumerWidget {
-  final _logger = Logger();
+  static final Logger _logger = Logger();

-  LogsActionsMenu({super.key});
+  const LogsActionsMenu({super.key});
lib/services/logger_export_service.dart (1)

50-68: Consider cleaning up the temp file after sharing.

The temp directory can grow if share files are never deleted. A try/finally around Share.shareXFiles keeps storage tidy.

♻️ Possible cleanup
   static Future<void> shareLogs(File file) async {
     final xFile = XFile(file.path);
-    await Share.shareXFiles(
-      [xFile],
-      subject: 'Mostro P2P Logs',
-      text: 'Application logs from Mostro P2P',
-    );
+    try {
+      await Share.shareXFiles(
+        [xFile],
+        subject: 'Mostro P2P Logs',
+        text: 'Application logs from Mostro P2P',
+      );
+    } finally {
+      try {
+        if (await file.exists()) {
+          await file.delete();
+        }
+      } catch (_) {
+        // swallow cleanup errors
+      }
+    }
   }

Refactors log export and sharing to utilize localized strings for file content, subject, and text.

This change ensures a consistent user experience across different languages
when exporting and sharing logs by using the app's localization system. It also includes a title to the logs file, generated timestamp and the total number of logs written.
Copy link
Member

@Catrya Catrya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BraCR10 me funciona bien, pero cuando comparto los logs, por ejemplo los envio a telegram, si quiero regresar a la app no puedo, se queda dentro de telegram aunque intente ir hacia atras, debo cerrar mostro app y volverla a abrir para que salga de ahi.
Lo otro es que si acabo de enviar los logs a telegram, e intento nuevamente no puedo, sino que debo cerrar mostro app y volverla a abrir.

Cuando puedas revisa eso por si acaso, no estoy segura de si es un problema de telegram propiamente.

Copy link
Member

@Catrya Catrya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tACK al parecer el problma que me da es de telegram, no de la app de mostro

Copy link
Member

@grunch grunch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK

@grunch grunch merged commit bfe923b into MostroP2P:main Jan 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants