TF-3479 Update logic Show <-> Hide <-> Minimize multiple composer

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-03-11 16:27:44 +07:00
committed by Dat H. Pham
parent a0160f09f3
commit d2e5d35755
5 changed files with 100 additions and 89 deletions
@@ -108,5 +108,7 @@ class ResponsiveUtils {
} }
} }
bool isMatchedDesktopWidth(double width) => width >= minDesktopWidth;
static bool isMatchedMobileWidth(double width) => width < minTabletWidth; static bool isMatchedMobileWidth(double width) => width < minTabletWidth;
} }
@@ -21,6 +21,7 @@ class ComposerManager extends GetxController {
void addComposer(ComposerArguments composerArguments) { void addComposer(ComposerArguments composerArguments) {
final id = DateTime.now().millisecondsSinceEpoch.toString(); final id = DateTime.now().millisecondsSinceEpoch.toString();
log('ComposerManager::addComposer:Id = $id');
ComposerBindings(composerId: id, composerArguments: composerArguments).dependencies(); ComposerBindings(composerId: id, composerArguments: composerArguments).dependencies();
composers[id] = ComposerView(key: Key(id), composerId: id); composers[id] = ComposerView(key: Key(id), composerId: id);
@@ -30,6 +31,7 @@ class ComposerManager extends GetxController {
} }
void removeComposer(String id) { void removeComposer(String id) {
log('ComposerManager::removeComposer:Id = $id');
if (!composers.containsKey(id)) return; if (!composers.containsKey(id)) return;
composerIdsQueue.remove(id); composerIdsQueue.remove(id);
@@ -70,7 +72,7 @@ class ComposerManager extends GetxController {
- ComposerStyle.composerExpandMoreButtonMaxWidth - ComposerStyle.composerExpandMoreButtonMaxWidth
- ComposerStyle.padding * 2 - ComposerStyle.padding * 2
- (countDisplayedComposer - 1) * ComposerStyle.space; - (countDisplayedComposer - 1) * ComposerStyle.space;
log('ComposerManager::_getSizeToArrangeComposers:screenWidth = $screenWidth | availableScreenWidth = $availableScreenWidth | totalOpenedComposersWidth = $totalOpenedComposersWidth'); log('ComposerManager::_getSizeToArrangeComposers:ScreenWidth = $screenWidth | AvailableScreenWidth = $availableScreenWidth | TotalOpenedComposersWidth = $totalOpenedComposersWidth');
return ( return (
availableScreenWidth, availableScreenWidth,
totalOpenedComposersWidth, totalOpenedComposersWidth,
@@ -78,29 +80,12 @@ class ComposerManager extends GetxController {
); );
} }
void _showMinimizedComposersIfOverflow({
required double availableScreenWidth,
required double totalOpenedComposersWidth,
required Map<String, ComposerController> composerControllers,
}) {
final currentHiddenComposerIds = hiddenComposerIds;
if (currentHiddenComposerIds.isEmpty) return;
for (var index = currentHiddenComposerIds.length - 1; index >= 0; index--) {
final newTotalWidth = totalOpenedComposersWidth + ComposerStyle.minimizeWidth;
if (newTotalWidth > availableScreenWidth) break;
final id = currentHiddenComposerIds.elementAt(index);
composerControllers[id]!.setScreenDisplayMode(ScreenDisplayMode.minimize);
totalOpenedComposersWidth = newTotalWidth;
}
}
void _hideComposersIfFit({ void _hideComposersIfFit({
required double availableScreenWidth, required double availableScreenWidth,
required double totalOpenedComposersWidth, required double totalOpenedComposersWidth,
required Map<String, ComposerController> composerControllers, required Map<String, ComposerController> composerControllers,
}) { }) {
log('ComposerManager::_hideComposersIfFit:');
final currentDisplayedComposerIds = displayedComposerIds; final currentDisplayedComposerIds = displayedComposerIds;
if (currentDisplayedComposerIds.isEmpty) return; if (currentDisplayedComposerIds.isEmpty) return;
@@ -129,16 +114,11 @@ class ComposerManager extends GetxController {
} }
void arrangeComposerWhenComposerQueueChanged({required double screenWidth}) { void arrangeComposerWhenComposerQueueChanged({required double screenWidth}) {
log('ComposerManager::arrangeComposerWhenComposerQueueChanged:ScreenWidth = $screenWidth');
var (availableScreenWidth, totalOpenedComposersWidth, composerControllers) = var (availableScreenWidth, totalOpenedComposersWidth, composerControllers) =
_getSizeToArrangeComposer(screenWidth: screenWidth); _getSizeToArrangeComposer(screenWidth: screenWidth);
if (totalOpenedComposersWidth < availableScreenWidth) { if (totalOpenedComposersWidth > availableScreenWidth) {
_showMinimizedComposersIfOverflow(
availableScreenWidth: availableScreenWidth,
totalOpenedComposersWidth: totalOpenedComposersWidth,
composerControllers: composerControllers,
);
} else if (totalOpenedComposersWidth > availableScreenWidth) {
_hideComposersIfFit( _hideComposersIfFit(
availableScreenWidth: availableScreenWidth, availableScreenWidth: availableScreenWidth,
totalOpenedComposersWidth: totalOpenedComposersWidth, totalOpenedComposersWidth: totalOpenedComposersWidth,
@@ -197,13 +177,7 @@ class ComposerManager extends GetxController {
var (availableScreenWidth, totalOpenedComposersWidth, composerControllers) = var (availableScreenWidth, totalOpenedComposersWidth, composerControllers) =
_getSizeToArrangeComposer(screenWidth: screenWidth); _getSizeToArrangeComposer(screenWidth: screenWidth);
if (totalOpenedComposersWidth < availableScreenWidth) { if (totalOpenedComposersWidth > availableScreenWidth) {
_showMinimizedComposersIfOverflow(
availableScreenWidth: availableScreenWidth,
totalOpenedComposersWidth: totalOpenedComposersWidth,
composerControllers: composerControllers,
);
} else if (totalOpenedComposersWidth > availableScreenWidth) {
_hideComposersPreferringMinimizedIfFit( _hideComposersPreferringMinimizedIfFit(
updatedComposerId: updatedComposerId, updatedComposerId: updatedComposerId,
availableScreenWidth: availableScreenWidth, availableScreenWidth: availableScreenWidth,
@@ -279,12 +253,19 @@ class ComposerManager extends GetxController {
} }
void showComposerIfHidden(String composerId) { void showComposerIfHidden(String composerId) {
log('ComposerManager::showComposerIfHidden:Id = $composerId');
if (!composers.containsKey(composerId)) return; if (!composers.containsKey(composerId)) return;
composerIdsQueue.remove(composerId); composerIdsQueue.remove(composerId);
composerIdsQueue.add(composerId); composerIdsQueue.add(composerId);
final composerView = getComposerView(composerId); final composerView = getComposerView(composerId);
composerView.controller.setScreenDisplayMode(ScreenDisplayMode.normal); composerView.controller.setScreenDisplayMode(ScreenDisplayMode.normal);
_arrangeComposerIfNeeded(); if (currentContext != null) {
arrangeComposerWhenComposerDisplayModeChanged(
screenWidth: _responsiveUtils.getSizeScreenWidth(currentContext!),
updatedComposerId: composerId,
newDisplayMode: ScreenDisplayMode.normal,
);
}
} }
ComposerView getComposerView(String id) => composers[id]!; ComposerView getComposerView(String id) => composers[id]!;
@@ -1,5 +1,4 @@
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/update_screen_display_mode_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/update_screen_display_mode_extension.dart';
@@ -8,84 +7,90 @@ import 'package:tmail_ui_user/features/composer/presentation/styles/composer_sty
import 'package:tmail_ui_user/features/composer/presentation/widgets/web/expand_composer_button.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/web/expand_composer_button.dart';
class ComposerOverlayView extends StatelessWidget { class ComposerOverlayView extends StatelessWidget {
final ComposerManager _composerManager = Get.find<ComposerManager>(); final ComposerManager composerManager;
final ResponsiveUtils _responsiveUtils = Get.find<ResponsiveUtils>(); final bool isDesktopScreen;
ComposerOverlayView({super.key}); const ComposerOverlayView({
super.key,
required this.composerManager,
required this.isDesktopScreen,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final screenWidth = MediaQuery.sizeOf(context).width;
if (_composerManager.composers.isNotEmpty) {
_composerManager.arrangeComposerWhenResponsiveChanged(screenWidth: screenWidth);
}
return Obx(() { return Obx(() {
final composers = _composerManager.composers; final composers = composerManager.composers;
final composerIdsQueue = _composerManager.composerIdsQueue; final composerIdsQueue = composerManager.composerIdsQueue;
if (composers.isEmpty || composerIdsQueue.isEmpty) return const SizedBox.shrink(); if (composers.isEmpty || composerIdsQueue.isEmpty) return const SizedBox.shrink();
if (!_responsiveUtils.isDesktop(context)) { if (!isDesktopScreen) {
final firstResponsiveComposerView = _composerManager.firstComposerViewWhenResponsiveChanged; final firstResponsiveComposerView = composerManager.firstComposerViewWhenResponsiveChanged;
if (firstResponsiveComposerView != null) return firstResponsiveComposerView; if (firstResponsiveComposerView != null) return firstResponsiveComposerView;
} }
final fullScreenComposerView = _composerManager.firstFullScreenComposerView; final fullScreenComposerView = composerManager.firstFullScreenComposerView;
if (fullScreenComposerView != null) return fullScreenComposerView; if (fullScreenComposerView != null) return fullScreenComposerView;
if (composerIdsQueue.length == 1) { if (composerIdsQueue.length == 1) {
final composerView = _composerManager.getComposerView(composerIdsQueue.first); final composerView = composerManager.getComposerView(composerIdsQueue.first);
if (composerView.controller.isHiddenScreen) { if (composerView.controller.isHiddenScreen) {
return Align( return Stack(
alignment: AlignmentDirectional.bottomEnd, children: [
child: SingleChildScrollView( Align(
scrollDirection: Axis.horizontal, alignment: AlignmentDirectional.bottomEnd,
child: Padding( child: SingleChildScrollView(
padding: const EdgeInsetsDirectional.all(ComposerStyle.padding), scrollDirection: Axis.horizontal,
child: ExpandComposerButton( child: Padding(
countComposerHidden: 1, padding: const EdgeInsetsDirectional.all(ComposerStyle.padding),
onRemoveHiddenComposerItem: (controller) => child: ExpandComposerButton(
controller.handleClickCloseComposer(context), countComposerHidden: 1,
onShowComposerAction: _composerManager.showComposerIfHidden, onRemoveHiddenComposerItem: (controller) =>
controller.handleClickCloseComposer(context),
onShowComposerAction: composerManager.showComposerIfHidden,
),
),
), ),
), ),
), ],
); );
} else { } else {
return composerView; return composerView;
} }
} }
final countComposerHidden = _composerManager.countComposerHidden; final countComposerHidden = composerManager.countComposerHidden;
final visibleComposers = composerIdsQueue final visibleComposers = composerIdsQueue
.map(_composerManager.getComposerView) .map(composerManager.getComposerView)
.where((view) => !view.controller.isHiddenScreen) .where((view) => !view.controller.isHiddenScreen)
.toList(); .toList();
return Align( return Stack(
alignment: AlignmentDirectional.bottomEnd, children: [
child: SingleChildScrollView( Align(
scrollDirection: Axis.horizontal, alignment: AlignmentDirectional.bottomEnd,
child: Padding( child: SingleChildScrollView(
padding: const EdgeInsetsDirectional.all(ComposerStyle.padding), scrollDirection: Axis.horizontal,
child: Row( child: Padding(
crossAxisAlignment: CrossAxisAlignment.end, padding: const EdgeInsetsDirectional.all(ComposerStyle.padding),
mainAxisSize: MainAxisSize.min, child: Row(
children: [ crossAxisAlignment: CrossAxisAlignment.end,
if (countComposerHidden > 0) mainAxisSize: MainAxisSize.min,
ExpandComposerButton( children: [
countComposerHidden: countComposerHidden, if (countComposerHidden > 0)
onRemoveHiddenComposerItem: (controller) => ExpandComposerButton(
controller.handleClickCloseComposer(context), countComposerHidden: countComposerHidden,
onShowComposerAction: _composerManager.showComposerIfHidden, onRemoveHiddenComposerItem: (controller) =>
), controller.handleClickCloseComposer(context),
...visibleComposers, onShowComposerAction: composerManager.showComposerIfHidden,
], ),
...visibleComposers,
],
),
),
), ),
), ),
), ],
); );
}); });
} }
@@ -825,8 +825,8 @@ class MailboxDashBoardController extends ReloadableController
} }
} }
void hideMailboxMenuWhenScreenSizeChange(BuildContext context) { void hideMailboxMenuWhenScreenSizeChange() {
if (responsiveUtils.isWebDesktop(context) && isDrawerOpen) { if (isDrawerOpen) {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
closeMailboxMenuDrawer(); closeMailboxMenuDrawer();
}); });
@@ -50,8 +50,6 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
controller.hideMailboxMenuWhenScreenSizeChange(context);
return Portal( return Portal(
child: Stack(children: [ child: Stack(children: [
ResponsiveWidget( ResponsiveWidget(
@@ -198,7 +196,32 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
} }
}), }),
), ),
ComposerOverlayView(), Align(
alignment: AlignmentDirectional.bottomEnd,
child: LayoutBuilder(
builder: ((context, constraints) {
log('MailboxDashBoardView::build:LayoutBuilder:Constraints = $constraints');
final screenWidth = constraints.maxWidth;
final composerManager = controller.composerManager;
final isDesktopScreen = controller.responsiveUtils.isMatchedDesktopWidth(screenWidth);
log('MailboxDashBoardView::build:ScreenWidth = $screenWidth | isDesktopScreen = $isDesktopScreen');
if (isDesktopScreen) {
controller.hideMailboxMenuWhenScreenSizeChange();
}
if (composerManager.composers.isNotEmpty) {
log('ComposerOverlayView::build:arrangeComposerWhenResponsiveChanged');
composerManager.arrangeComposerWhenResponsiveChanged(screenWidth: screenWidth);
}
return ComposerOverlayView(
composerManager: composerManager,
isDesktopScreen: isDesktopScreen,
);
}),
),
),
Obx(() => controller.searchMailboxActivated.value == true && !controller.responsiveUtils.isWebDesktop(context) Obx(() => controller.searchMailboxActivated.value == true && !controller.responsiveUtils.isWebDesktop(context)
? const SearchMailboxView() ? const SearchMailboxView()
: const SizedBox.shrink() : const SizedBox.shrink()