TF-2919 Fix memory leak when attach files in composer

This commit is contained in:
dab246
2024-06-10 18:59:24 +07:00
committed by Dat H. Pham
parent 9d800ba798
commit 82b51082fc
5 changed files with 77 additions and 31 deletions
@@ -2,7 +2,6 @@ import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/utils/platform_info.dart';
import 'package:extended_text/extended_text.dart';
import 'package:filesize/filesize.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
@@ -10,7 +9,7 @@ import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/attachment_item_composer_widget_style.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_progress_loading_composer_widget.dart';
import 'package:tmail_ui_user/features/upload/domain/model/upload_task_id.dart';
import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_state.dart';
import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_status.dart';
typedef OnDeleteAttachmentAction = void Function(UploadTaskId uploadTaskId);
@@ -18,7 +17,12 @@ class AttachmentItemComposerWidget extends StatelessWidget with AppLoaderMixin {
final _imagePaths = Get.find<ImagePaths>();
final UploadFileState fileState;
final String fileIcon;
final String fileName;
final String fileSize;
final UploadFileStatus uploadStatus;
final double percentUploading;
final UploadTaskId uploadTaskId;
final double? maxWidth;
final EdgeInsetsGeometry? itemMargin;
final EdgeInsetsGeometry? itemPadding;
@@ -27,7 +31,12 @@ class AttachmentItemComposerWidget extends StatelessWidget with AppLoaderMixin {
AttachmentItemComposerWidget({
super.key,
required this.fileState,
required this.fileIcon,
required this.fileName,
required this.fileSize,
required this.uploadStatus,
required this.percentUploading,
required this.uploadTaskId,
this.maxWidth,
this.itemMargin,
this.itemPadding,
@@ -55,7 +64,7 @@ class AttachmentItemComposerWidget extends StatelessWidget with AppLoaderMixin {
Row(
children: [
SvgPicture.asset(
fileState.getIcon(_imagePaths),
fileIcon,
width: AttachmentItemComposerWidgetStyle.iconSize,
height: AttachmentItemComposerWidgetStyle.iconSize,
fit: BoxFit.fill
@@ -64,7 +73,7 @@ class AttachmentItemComposerWidget extends StatelessWidget with AppLoaderMixin {
Expanded(
child: PlatformInfo.isCanvasKit
? ExtendedText(
fileState.fileName,
fileName,
maxLines: 1,
overflowWidget: const TextOverflowWidget(
position: TextOverflowPosition.middle,
@@ -76,7 +85,7 @@ class AttachmentItemComposerWidget extends StatelessWidget with AppLoaderMixin {
style: AttachmentItemComposerWidgetStyle.labelTextStyle,
)
: Text(
fileState.fileName,
fileName,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: AttachmentItemComposerWidgetStyle.labelTextStyle,
@@ -84,14 +93,14 @@ class AttachmentItemComposerWidget extends StatelessWidget with AppLoaderMixin {
),
const SizedBox(width: AttachmentItemComposerWidgetStyle.space),
Text(
filesize(fileState.fileSize),
fileSize,
style: AttachmentItemComposerWidgetStyle.sizeLabelTextStyle
),
],
),
AttachmentProgressLoadingComposerWidget(
fileState: fileState,
padding: AttachmentItemComposerWidgetStyle.progressLoadingPadding,
uploadStatus: uploadStatus,
percentUploading: percentUploading,
)
],
),
@@ -103,7 +112,7 @@ class AttachmentItemComposerWidget extends StatelessWidget with AppLoaderMixin {
borderRadius: AttachmentItemComposerWidgetStyle.deleteIconRadius,
padding: AttachmentItemComposerWidgetStyle.deleteIconPadding,
iconColor: AttachmentItemComposerWidgetStyle.deleteIconColor,
onTapActionCallback: () => onDeleteAttachmentAction?.call(fileState.uploadTaskId),
onTapActionCallback: () => onDeleteAttachmentAction?.call(uploadTaskId),
)
],
),
@@ -1,27 +1,27 @@
import 'package:flutter/material.dart';
import 'package:percent_indicator/linear_percent_indicator.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/attachment_item_composer_widget_style.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/attachment_progress_loading_composer_widget_style.dart';
import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_state.dart';
import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_status.dart';
class AttachmentProgressLoadingComposerWidget extends StatelessWidget {
final UploadFileState fileState;
final EdgeInsetsGeometry? padding;
final UploadFileStatus uploadStatus;
final double percentUploading;
const AttachmentProgressLoadingComposerWidget({
super.key,
required this.fileState,
this.padding,
required this.uploadStatus,
required this.percentUploading,
});
@override
Widget build(BuildContext context) {
switch (fileState.uploadStatus) {
switch (uploadStatus) {
case UploadFileStatus.waiting:
return Padding(
padding: padding ?? EdgeInsets.zero,
child: const LinearProgressIndicator(
return const Padding(
padding: AttachmentItemComposerWidgetStyle.progressLoadingPadding,
child: LinearProgressIndicator(
color: AttachmentProgressLoadingComposerWidgetStyle.progressColor,
minHeight: AttachmentProgressLoadingComposerWidgetStyle.height,
backgroundColor: AttachmentProgressLoadingComposerWidgetStyle.backgroundColor,
@@ -29,13 +29,13 @@ class AttachmentProgressLoadingComposerWidget extends StatelessWidget {
);
case UploadFileStatus.uploading:
return Padding(
padding: padding ?? EdgeInsets.zero,
padding: AttachmentItemComposerWidgetStyle.progressLoadingPadding,
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
lineHeight:AttachmentProgressLoadingComposerWidgetStyle.height,
percent: fileState.percentUploading > 1.0
percent: percentUploading > 1.0
? 1.0
: fileState.percentUploading,
: percentUploading,
barRadius: const Radius.circular(AttachmentProgressLoadingComposerWidgetStyle.radius),
backgroundColor: AttachmentProgressLoadingComposerWidgetStyle.backgroundColor,
progressColor: AttachmentProgressLoadingComposerWidgetStyle.progressColor,
@@ -3,6 +3,7 @@ import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/presentation/views/list/sliver_grid_delegate_fixed_height.dart';
import 'package:filesize/filesize.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/attachment_item_composer_widget_style.dart';
@@ -73,8 +74,14 @@ class _MobileAttachmentComposerWidgetState extends State<MobileAttachmentCompose
primary: false,
itemCount: _listFileDisplayed.length,
itemBuilder: (context, index) {
final file = _listFileDisplayed[index];
return AttachmentItemComposerWidget(
fileState: _listFileDisplayed[index],
fileIcon: file.getIcon(_imagePaths),
fileName: file.fileName,
fileSize: filesize(file.fileSize),
uploadStatus: file.uploadStatus,
percentUploading: file.percentUploading,
uploadTaskId: file.uploadTaskId,
itemMargin: MobileAttachmentComposerWidgetStyle.itemMargin,
onDeleteAttachmentAction: widget.onDeleteAttachmentAction
);
@@ -130,8 +137,14 @@ class _MobileAttachmentComposerWidgetState extends State<MobileAttachmentCompose
crossAxisSpacing: MobileAttachmentComposerWidgetStyle.listItemSpace,
),
itemBuilder: (context, index) {
final file = _listFileDisplayed[index];
return AttachmentItemComposerWidget(
fileState: _listFileDisplayed[index],
fileIcon: file.getIcon(_imagePaths),
fileName: file.fileName,
fileSize: filesize(file.fileSize),
uploadStatus: file.uploadStatus,
percentUploading: file.percentUploading,
uploadTaskId: file.uploadTaskId,
itemMargin: MobileAttachmentComposerWidgetStyle.itemMargin,
itemPadding: const EdgeInsets.symmetric(horizontal: 8),
onDeleteAttachmentAction: widget.onDeleteAttachmentAction
@@ -1,5 +1,8 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:filesize/filesize.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/composer/presentation/styles/web/attachment_composer_widget_style.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_item_composer_widget.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_header_composer_widget.dart';
@@ -28,6 +31,7 @@ class AttachmentComposerWidget extends StatefulWidget {
class _AttachmentComposerWidgetState extends State<AttachmentComposerWidget> {
final ImagePaths _imagePaths = Get.find<ImagePaths>();
bool _isCollapsed = false;
@override
@@ -36,6 +40,12 @@ class _AttachmentComposerWidgetState extends State<AttachmentComposerWidget> {
_isCollapsed = widget.isCollapsed;
}
@override
void dispose() {
_isCollapsed = false;
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
@@ -66,8 +76,13 @@ class _AttachmentComposerWidgetState extends State<AttachmentComposerWidget> {
runSpacing: AttachmentComposerWidgetStyle.listItemSpace,
children: widget.listFileUploaded
.map((file) => AttachmentItemComposerWidget(
fileState: file,
onDeleteAttachmentAction: widget.onDeleteAttachmentAction
fileIcon: file.getIcon(_imagePaths),
fileName: file.fileName,
fileSize: filesize(file.fileSize),
uploadStatus: file.uploadStatus,
percentUploading: file.percentUploading,
uploadTaskId: file.uploadTaskId,
onDeleteAttachmentAction: widget.onDeleteAttachmentAction,
))
.toList(),
),
@@ -1,4 +1,6 @@
import 'dart:async';
import 'package:async/async.dart';
import 'package:collection/collection.dart';
import 'package:core/presentation/extensions/color_extension.dart';
@@ -45,6 +47,9 @@ class UploadController extends BaseController {
final StreamGroup<Either<Failure, Success>> _progressUploadInlineImageStateStreamGroup
= StreamGroup<Either<Failure, Success>>.broadcast();
StreamSubscription? _uploadAttachmentStreamSubscription;
StreamSubscription? _uploadInlineImageStreamSubscription;
final UploadFileStateList _uploadingStateFiles = UploadFileStateList();
final UploadFileStateList _uploadingStateInlineFiles = UploadFileStateList();
@@ -58,17 +63,21 @@ class UploadController extends BaseController {
@override
void onClose() {
listUploadAttachments.clear();
_uploadingStateFiles.clear();
_progressUploadStateStreamGroup.close();
_uploadingStateInlineFiles.clear();
_progressUploadInlineImageStateStreamGroup.close();
uploadInlineViewState.value = Right(UIClosedState());
dispatchState(Right(UIClosedState()));
_progressUploadStateStreamGroup.close();
_progressUploadInlineImageStateStreamGroup.close();
_uploadAttachmentStreamSubscription?.cancel();
_uploadInlineImageStreamSubscription?.cancel();
super.onClose();
}
void _registerProgressUploadStateStream() {
_progressUploadStateStreamGroup.stream.listen(_handleProgressUploadStateStream);
_progressUploadInlineImageStateStreamGroup.stream.listen(_handleProgressUploadInlineImageStateStream);
_uploadAttachmentStreamSubscription = _progressUploadStateStreamGroup.stream.listen(_handleProgressUploadStateStream);
_uploadInlineImageStreamSubscription = _progressUploadInlineImageStateStreamGroup.stream.listen(_handleProgressUploadInlineImageStateStream);
}
void _handleProgressUploadStateStream(Either<Failure, Success> uploadState) {