simplify: dedupe boilerplate and remove dead code across all layers

This commit is contained in:
2026-07-13 22:22:39 +02:00
parent 15791423ea
commit 398b147c76
69 changed files with 345 additions and 651 deletions
@@ -166,13 +166,24 @@ Future<void> _afterExternalFilesUploaded(
GetRoomResponseObject room,
List<String> uploadedRemotePaths,
PendingShare share,
) async {
) => _runShareFlow(
context,
action: () =>
shareFilesToChat(token: room.token, remoteFilePaths: uploadedRemotePaths),
onSuccess: () => _setExternalDraftAndOpenChat(context, room, share),
);
/// Shared share-flow scaffolding: shows the blocking spinner, runs [action],
/// maps failures to an error dialog (popping the spinner first), and invokes
/// [onSuccess] on success while still mounted.
Future<void> _runShareFlow(
BuildContext context, {
required Future<void> Function() action,
required VoidCallback onSuccess,
}) async {
unawaited(_showBlockingSpinner(context));
try {
await shareFilesToChat(
token: room.token,
remoteFilePaths: uploadedRemotePaths,
);
await action();
} catch (e) {
if (context.mounted) Navigator.of(context).pop();
if (context.mounted) {
@@ -186,7 +197,7 @@ Future<void> _afterExternalFilesUploaded(
return;
}
if (!context.mounted) return;
_setExternalDraftAndOpenChat(context, room, share);
onSuccess();
}
void _setExternalDraftAndOpenChat(
@@ -213,61 +224,30 @@ Future<void> _internalShareFlow(
BuildContext context,
GetRoomResponseObject room,
RemoteFileRef file,
) async {
unawaited(_showBlockingSpinner(context));
try {
await shareFilesToChat(
token: room.token,
remoteFilePaths: [file.path],
);
} catch (e) {
if (context.mounted) Navigator.of(context).pop();
if (context.mounted) {
InfoDialog.show(
context,
errorToUserMessage(e),
title: 'Fehler',
copyable: true,
);
}
return;
}
if (!context.mounted) return;
_finishWithChat(context, room);
}
) => _runShareFlow(
context,
action: () =>
shareFilesToChat(token: room.token, remoteFilePaths: [file.path]),
onSuccess: () => _finishWithChat(context, room),
);
Future<void> _forwardMessageFlow(
BuildContext context,
GetRoomResponseObject room,
String? text,
RemoteFileRef? file,
) async {
unawaited(_showBlockingSpinner(context));
try {
) => _runShareFlow(
context,
action: () async {
if (file != null) {
await shareFilesToChat(
token: room.token,
remoteFilePaths: [file.path],
);
await shareFilesToChat(token: room.token, remoteFilePaths: [file.path]);
}
if (text != null && text.isNotEmpty) {
await SendMessage(room.token, SendMessageParams(text)).run();
}
} catch (e) {
if (context.mounted) Navigator.of(context).pop();
if (context.mounted) {
InfoDialog.show(
context,
errorToUserMessage(e),
title: 'Fehler',
copyable: true,
);
}
return;
}
if (!context.mounted) return;
_finishWithChat(context, room);
}
},
onSuccess: () => _finishWithChat(context, room),
);
/// Modal progress overlay shown during share-API roundtrips. The dialog is
/// popped together with the picker by the subsequent popUntil(isFirst).
@@ -121,26 +121,15 @@ class ShareTargetPage extends StatelessWidget {
Widget _buildFilePreview(BuildContext context) {
if (share.filePaths.length == 1) {
final path = share.filePaths.first;
final name = path.split(Platform.pathSeparator).last;
return ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 320),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainer,
borderRadius: BorderRadius.circular(12),
),
clipBehavior: Clip.antiAlias,
child: _isImagePath(path)
? Image.file(
File(path),
fit: BoxFit.contain,
// Decode at most ~1080px so 50-MP gallery photos don't
// balloon the decode buffer just to render at <320px high.
cacheWidth: 1080,
errorBuilder: (_, _, _) => _fileFallbackLarge(name),
)
: _fileFallbackLarge(name),
// Decode at most ~1080px so 50-MP gallery photos don't balloon the
// decode buffer just to render at <320px high.
child: _filePreviewTile(
context,
share.filePaths.first,
fit: BoxFit.contain,
cacheWidth: 1080,
),
);
}
@@ -153,28 +142,38 @@ class ShareTargetPage extends StatelessWidget {
mainAxisSpacing: 10,
),
itemCount: share.filePaths.length,
itemBuilder: (context, i) {
final path = share.filePaths[i];
final name = path.split(Platform.pathSeparator).last;
return Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainer,
borderRadius: BorderRadius.circular(12),
),
clipBehavior: Clip.antiAlias,
child: _isImagePath(path)
? Image.file(
File(path),
fit: BoxFit.cover,
// Grid tiles are ~half-screen wide; 480px decode is
// sharp on 3x displays without blowing up memory when
// many files are shared at once.
cacheWidth: 480,
errorBuilder: (_, _, _) => _fileFallbackLarge(name),
)
: _fileFallbackLarge(name),
);
},
// Grid tiles are ~half-screen wide; 480px decode is sharp on 3x displays
// without blowing up memory when many files are shared at once.
itemBuilder: (context, i) => _filePreviewTile(
context,
share.filePaths[i],
fit: BoxFit.cover,
cacheWidth: 480,
),
);
}
Widget _filePreviewTile(
BuildContext context,
String path, {
required BoxFit fit,
required int cacheWidth,
}) {
final name = path.split(Platform.pathSeparator).last;
return Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainer,
borderRadius: BorderRadius.circular(12),
),
clipBehavior: Clip.antiAlias,
child: _isImagePath(path)
? Image.file(
File(path),
fit: fit,
cacheWidth: cacheWidth,
errorBuilder: (_, _, _) => _fileFallbackLarge(name),
)
: _fileFallbackLarge(name),
);
}