feat: save raw email to temp dir and add Share action to SnackBar (#115)
Save the .eml file to the temporary directory (reliable on all platforms) and display a Share action in the SnackBar so users can send the file to any app — including the Files app — which properly registers it with Android's MediaStore and makes it visible in the recently-used list. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
e327b42312
commit
de66081813
@@ -9,6 +9,7 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:open_filex/open_filex.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
import 'package:sharedinbox/core/models/email.dart';
|
||||
import 'package:sharedinbox/core/models/undo_action.dart';
|
||||
@@ -517,13 +518,7 @@ class _EmailDetailScreenState extends ConsumerState<EmailDetailScreen> {
|
||||
String raw,
|
||||
) async {
|
||||
try {
|
||||
Directory dir;
|
||||
try {
|
||||
dir =
|
||||
(await getDownloadsDirectory()) ?? (await getTemporaryDirectory());
|
||||
} catch (_) {
|
||||
dir = await getTemporaryDirectory();
|
||||
}
|
||||
final dir = await getTemporaryDirectory();
|
||||
final subject = (header?.subject ?? 'email')
|
||||
.replaceAll(RegExp(r'[^\w\s-]'), '_')
|
||||
.trim();
|
||||
@@ -532,7 +527,15 @@ class _EmailDetailScreenState extends ConsumerState<EmailDetailScreen> {
|
||||
await file.writeAsString(raw);
|
||||
if (!context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Saved $filename to ${dir.path}')),
|
||||
SnackBar(
|
||||
content: Text('Saved $filename'),
|
||||
action: SnackBarAction(
|
||||
label: 'Share',
|
||||
onPressed: () => SharePlus.instance.share(
|
||||
ShareParams(files: [XFile(file.path)]),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
|
||||
@@ -60,6 +60,7 @@ dependencies:
|
||||
|
||||
# App version metadata for crash reports
|
||||
package_info_plus: ^8.0.0
|
||||
share_plus: ^12.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -12,14 +12,11 @@ import 'package:sharedinbox/di.dart';
|
||||
|
||||
import 'helpers.dart';
|
||||
|
||||
// Fake PathProviderPlatform so _downloadRaw resolves getDownloadsDirectory /
|
||||
// getTemporaryDirectory via pure microtasks instead of calling xdg-user-dir.
|
||||
// Fake PathProviderPlatform so _downloadRaw resolves getTemporaryDirectory
|
||||
// via pure microtasks instead of calling xdg-user-dir.
|
||||
class _FakePathProviderPlatform extends PathProviderPlatform {
|
||||
@override
|
||||
Future<String?> getTemporaryPath() async => '/tmp';
|
||||
|
||||
@override
|
||||
Future<String?> getDownloadsPath() async => '/tmp';
|
||||
}
|
||||
|
||||
// IOOverrides subclass that stubs File creation so _downloadRaw completes
|
||||
@@ -261,7 +258,7 @@ void main() {
|
||||
});
|
||||
|
||||
await tester.tap(find.text('Download'));
|
||||
// Each pump drains one microtask level: getDownloadsDirectory, then
|
||||
// Each pump drains one microtask level: getTemporaryDirectory, then
|
||||
// writeAsString, then _downloadRaw return, then Navigator.pop.
|
||||
for (var i = 0; i < 10; i++) {
|
||||
await tester.pump(Duration.zero);
|
||||
@@ -270,6 +267,8 @@ void main() {
|
||||
|
||||
// Dialog must be dismissed after download completes.
|
||||
expect(find.text('Raw Email'), findsNothing);
|
||||
// SnackBar with Share action must be visible.
|
||||
expect(find.text('Share'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Show Mail Structure opens dialog with MIME parts', (
|
||||
|
||||
Reference in New Issue
Block a user