@ -6,12 +6,11 @@ import 'package:flutter/material.dart';
import ' package:cross_file/cross_file.dart ' ;
import ' package:flutter_gen/gen_l10n/l10n.dart ' ;
import ' package:future_loading_dialog/future_loading_dialog.dart ' ;
import ' package:matrix/matrix.dart ' ;
import ' package:mime/mime.dart ' ;
import ' package:fluffychat/config/app_config.dart ' ;
import ' package:fluffychat/utils/ error_reporter .dart' ;
import ' package:fluffychat/utils/ localized_exception_extension .dart' ;
import ' package:fluffychat/utils/matrix_sdk_extensions/matrix_file_extension.dart ' ;
import ' package:fluffychat/utils/platform_infos.dart ' ;
import ' package:fluffychat/utils/size_string.dart ' ;
@ -20,10 +19,12 @@ import '../../utils/resize_video.dart';
class SendFileDialog extends StatefulWidget {
final Room room ;
final List < XFile > files ;
final BuildContext outerContext ;
const SendFileDialog ( {
required this . room ,
required this . files ,
required this . outerContext ,
super . key ,
} ) ;
@ -38,65 +39,98 @@ class SendFileDialogState extends State<SendFileDialog> {
static const int minSizeToCompress = 20 * 1024 ;
Future < void > _send ( ) async {
final scaffoldMessenger = ScaffoldMessenger . of ( c ontext) ;
final scaffoldMessenger = ScaffoldMessenger . of ( widget. outerC ontext) ;
final l10n = L10n . of ( context ) ! ;
Navigator . of ( context , rootNavigator: false ) . pop ( ) ;
try {
scaffoldMessenger . showLoadingSnackBar ( l10n . prepareSendingAttachment ) ;
Navigator . of ( context , rootNavigator: false ) . pop ( ) ;
final clientConfig = await widget . room . client . getConfig ( ) ;
final maxUploadSize = clientConfig . mUploadSize ? ? 100 * 1024 * 1024 ;
showFutureLoadingDialog (
context: context ,
future: ( ) async {
final clientConfig = await widget . room . client . getConfig ( ) ;
final m axUploadSize = clientConfig . mUploadSize ? ? 100 * 1024 * 1024 ;
for ( final xfile in widget . files ) {
final MatrixFile file ;
MatrixImageFile ? thumbnail ;
final length = await xfile . length ( ) ;
final m imeType = xfile . mimeType ? ? lookupMimeType ( xfile . path ) ;
for ( final xfile in widget . files ) {
final MatrixFile file ;
MatrixImageFile ? thumbnail ;
final length = await xfile . length ( ) ;
final mimeType = xfile . mimeType ? ? lookupMimeType ( xfile . path ) ;
/ / If file is a video , shrink it !
if ( PlatformInfos . isMobile & &
mimeType ! = null & &
mimeType . startsWith ( ' video ' ) & &
length > minSizeToCompress & &
! origImage ) {
scaffoldMessenger . showLoadingSnackBar ( l10n . compressVideo ) ;
file = await xfile . resizeVideo ( ) ;
scaffoldMessenger . showLoadingSnackBar ( l10n . generatingVideoThumbnail ) ;
thumbnail = await xfile . getVideoThumbnail ( ) ;
} else {
/ / Else we just create a MatrixFile
file = MatrixFile (
bytes: await xfile . readAsBytes ( ) ,
name: xfile . name ,
mimeType: xfile . mimeType ,
) . detectFileType ;
}
/ / If file is a video , shrink it !
if ( mimeType ! = null & &
mimeType . startsWith ( ' video ' ) & &
length > minSizeToCompress & &
! origImage ) {
file = await xfile . resizeVideo ( ) ;
thumbnail = await xfile . getVideoThumbnail ( ) ;
} else {
/ / Else we just create a MatrixFile
file = MatrixFile (
bytes: await xfile . readAsBytes ( ) ,
name: xfile . name ,
mimeType: xfile . mimeType ,
) . detectFileType ;
}
if ( file . bytes . length > maxUploadSize ) {
throw FileTooBigMatrixException ( length , maxUploadSize ) ;
}
if ( widget . files . length > 1 ) {
scaffoldMessenger . showLoadingSnackBar (
l10n . sendingAttachmentCountOfCount (
widget . files . indexOf ( xfile ) + 1 ,
widget . files . length ,
) ,
) ;
} else {
scaffoldMessenger . showLoadingSnackBar ( l10n . sendingAttachment ) ;
}
if ( file . bytes . length > maxUploadSize ) {
throw FileTooBigMatrixException ( length , maxUploadSize ) ;
try {
await widget . room . sendFileEvent (
file ,
thumbnail: thumbnail ,
shrinkImageMaxDimension: origImage ? null : 1600 ,
) ;
} on MatrixException catch ( e ) {
final retryAfterMs = e . retryAfterMs ;
if ( e . error ! = MatrixError . M_LIMIT_EXCEEDED | | retryAfterMs = = null ) {
rethrow ;
}
final retryAfterDuration =
Duration ( milliseconds: retryAfterMs + 1000 ) ;
scaffoldMessenger . showSnackBar (
SnackBar (
content: Text (
l10n . serverLimitReached ( retryAfterDuration . inSeconds ) ,
) ,
) ,
) ;
await Future . delayed ( retryAfterDuration ) ;
scaffoldMessenger . showLoadingSnackBar ( l10n . sendingAttachment ) ;
widget . room
. sendFileEvent (
await widget . room . sendFileEvent (
file ,
thumbnail: thumbnail ,
shrinkImageMaxDimension: origImage ? null : 1600 ,
)
. catchError (
( e , s ) {
if ( e is FileTooBigMatrixException ) {
scaffoldMessenger . showSnackBar (
SnackBar ( content: Text ( l10n . fileIsTooBigForServer ) ) ,
) ;
return null ;
}
ErrorReporter ( context , ' Unable to send file ' )
. onErrorCallback ( e , s ) ;
return null ;
} ,
) ;
}
} ,
) ;
}
} catch ( e ) {
scaffoldMessenger . clearSnackBars ( ) ;
scaffoldMessenger . showSnackBar (
SnackBar (
content: Text ( e . toLocalizedString ( widget . outerContext ) ) ,
duration: const Duration ( seconds: 30 ) ,
showCloseIcon: true ,
) ,
) ;
rethrow ;
}
return ;
}
@ -270,3 +304,30 @@ class SendFileDialogState extends State<SendFileDialog> {
) ;
}
}
extension on ScaffoldMessengerState {
ScaffoldFeatureController < SnackBar , SnackBarClosedReason > showLoadingSnackBar (
String title ,
) {
clearSnackBars ( ) ;
return showSnackBar (
SnackBar (
duration: const Duration ( minutes: 5 ) ,
dismissDirection: DismissDirection . none ,
content: Row (
children: [
const SizedBox (
width: 16 ,
height: 16 ,
child: CircularProgressIndicator . adaptive (
strokeWidth: 2 ,
) ,
) ,
const SizedBox ( width: 16 ) ,
Text ( title ) ,
] ,
) ,
) ,
) ;
}
}