TF-3479 Always persist as much normal screen as possible

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-02-14 16:53:17 +07:00
committed by Dat H. Pham
parent 16cb8c8a37
commit c21a9dda24
8 changed files with 188 additions and 115 deletions
@@ -30,50 +30,19 @@ extension UpdateScreenDisplayModeExtension on ComposerController {
}
}
void setScreenDisplayMode(ScreenDisplayMode displayMode) =>
screenDisplayMode.value = displayMode;
void setScreenDisplayMode(ScreenDisplayMode newDisplayMode) =>
screenDisplayMode.value = newDisplayMode;
bool setToMinimizeIfNormal() {
if (isNormalScreen) {
screenDisplayMode.value = ScreenDisplayMode.minimize;
return true;
}
return false;
}
void updateDisplayModeForComposerQueue(ScreenDisplayMode displayMode) {
void updateDisplayModeForComposerQueue(ScreenDisplayMode newDisplayMode) {
if (composerId == null || currentContext == null) return;
final composerManager = mailboxDashBoardController.composerManager;
final screenWidth = responsiveUtils.getSizeScreenWidth(currentContext!);
if (!composerManager.isExceedsScreenSize(screenWidth: screenWidth)) {
return;
}
if (displayMode == ScreenDisplayMode.normal) {
final recordComposerIds = composerManager.findSurroundingComposerIds(composerId!);
final nextComposer = recordComposerIds.nextTargetId;
final prevComposer = recordComposerIds.previousTargetId;
if (nextComposer != null && composerManager.getComposerView(nextComposer).controller.setToMinimizeIfNormal()) {
return;
}
if (prevComposer != null && composerManager.getComposerView(prevComposer).controller.setToMinimizeIfNormal()) {
return;
}
final firstNormalComposerId = composerManager.findFirstNormalComposerIdInQueue();
if (firstNormalComposerId != null && firstNormalComposerId != composerId) {
composerManager
.getComposerView(firstNormalComposerId)
.controller
.setScreenDisplayMode(ScreenDisplayMode.minimize);
}
} else if (displayMode == ScreenDisplayMode.fullScreen) {
}
composerManager.syncComposerQueue(screenWidth: screenWidth);
composerManager.syncComposerStateWhenComposerDisplayModeChanged(
screenWidth: screenWidth,
updatedComposerId: composerId!,
newDisplayMode: newDisplayMode,
);
}
}
@@ -1,7 +1,6 @@
import 'dart:collection';
import 'package:collection/collection.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/utils/app_logger.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_bindings.dart';
@@ -41,7 +40,7 @@ class ComposerManager extends GetxController {
void _syncQueueIfNeeded() {
if (currentContext != null && composerIdsQueue.isNotEmpty) {
syncComposerQueue(
syncComposerStateWhenComposerQueueChanged(
screenWidth: _responsiveUtils.getSizeScreenWidth(currentContext!),
);
}
@@ -71,68 +70,139 @@ class ComposerManager extends GetxController {
.firstWhereOrNull((id) => getComposerView(id).controller.isNormalScreen);
}
bool isExceedsScreenSize({required double screenWidth}) {
final availableWidth = screenWidth
- ComposerUtils.composerExpandMoreButtonMaxWidth
- ComposerUtils.padding * 2;
double totalWidth = composerIdsQueue.fold<double>(
0,
(sum, id) => sum + getComposerView(id).controller.composerWidth,
);
bool isExceedsScreenSize = totalWidth > availableWidth;
log('ComposerManager::isExceedsScreenSize:isExceedsScreenSize = $isExceedsScreenSize');
return isExceedsScreenSize;
}
void syncComposerQueue({required double screenWidth}) {
if (composerIdsQueue.isEmpty) return;
log('ComposerManager::syncComposerQueue:screenWidth = $screenWidth');
final availableWidth = screenWidth
- ComposerUtils.composerExpandMoreButtonMaxWidth
- ComposerUtils.padding * 2;
log('ComposerManager::syncComposerQueue:availableWidth = $availableWidth');
(
double availableWidth,
double totalWidth,
Map<String, ComposerController> composerControllers
) _setUpDataToSyncComposerQueue({required double screenWidth}) {
double totalWidth = 0;
double countDisplayedComposer = 0;
final composerControllers = <String, ComposerController>{};
for (var id in composerIdsQueue) {
final controller = getComposerView(id).controller;
final composerWidth = controller.composerWidth;
if (!controller.isHiddenScreen) {
countDisplayedComposer++;
}
composerControllers[id] = controller;
totalWidth += composerWidth;
}
log('ComposerManager::syncComposerQueue:totalWidth = $totalWidth');
for (var id in composerIdsQueue) {
final controller = composerControllers[id]!;
if (controller.isNormalScreen) {
controller.setScreenDisplayMode(ScreenDisplayMode.minimize);
totalWidth -= (ComposerUtils.normalWidth - ComposerUtils.minimizeWidth);
} else if (controller.isMinimizeScreen) {
controller.setScreenDisplayMode(ScreenDisplayMode.hidden);
totalWidth -= ComposerUtils.minimizeWidth;
}
final availableWidth = screenWidth
- ComposerUtils.composerExpandMoreButtonMaxWidth
- ComposerUtils.padding * 3
- (countDisplayedComposer - 1) * ComposerUtils.space;
if (totalWidth <= availableWidth) break;
}
log('ComposerManager::syncComposerQueue:totalWidth_after = $totalWidth');
for (var id in composerIdsQueue) {
final controller = composerControllers[id]!;
final composerWidth = controller.composerWidth;
if (totalWidth + (ComposerUtils.normalWidth - composerWidth) <= availableWidth) {
controller.setScreenDisplayMode(ScreenDisplayMode.normal);
totalWidth += (ComposerUtils.normalWidth - composerWidth);
} else if (totalWidth + (ComposerUtils.minimizeWidth - composerWidth) <= availableWidth) {
controller.setScreenDisplayMode(ScreenDisplayMode.minimize);
totalWidth += (ComposerUtils.minimizeWidth - composerWidth);
}
}
log('ComposerManager::syncComposerQueue:totalWidth_finally = $totalWidth');
return (
availableWidth,
totalWidth,
composerControllers,
);
}
void syncComposerStateWhenComposerQueueChanged({required double screenWidth}) {
var (availableWidth, totalWidth, composerControllers) =
_setUpDataToSyncComposerQueue(screenWidth: screenWidth);
if (totalWidth < availableWidth) {
final currentHiddenComposerIds = hiddenComposerIds;
if (currentHiddenComposerIds.isEmpty) return;
for (var index = currentHiddenComposerIds.length - 1; index >= 0; index--) {
final newTotalWidth = totalWidth + ComposerUtils.minimizeWidth;
if (newTotalWidth > availableWidth) break;
final id = currentHiddenComposerIds.elementAt(index);
final controller = composerControllers[id]!;
controller.setScreenDisplayMode(ScreenDisplayMode.minimize);
totalWidth = newTotalWidth;
}
} else if (totalWidth > availableWidth) {
final currentDisplayedComposerIds = displayedComposerIds;
if (currentDisplayedComposerIds.isEmpty) return;
for (var id in currentDisplayedComposerIds) {
final controller = composerControllers[id]!;
if (controller.isNormalScreen) {
var newTotalWidth = totalWidth - (ComposerUtils.normalWidth - ComposerUtils.minimizeWidth);
var newDisplayMode = ScreenDisplayMode.minimize;
if (newTotalWidth > availableWidth) {
newTotalWidth = totalWidth - ComposerUtils.normalWidth;
newDisplayMode = ScreenDisplayMode.hidden;
}
controller.setScreenDisplayMode(newDisplayMode);
totalWidth = newTotalWidth;
} else if (controller.isMinimizeScreen) {
final newTotalWidth = totalWidth - ComposerUtils.minimizeWidth;
controller.setScreenDisplayMode(ScreenDisplayMode.hidden);
totalWidth = newTotalWidth;
}
if (totalWidth <= availableWidth) break;
}
}
}
void syncComposerStateWhenComposerDisplayModeChanged({
required double screenWidth,
required String updatedComposerId,
required ScreenDisplayMode newDisplayMode,
}) {
if (composerIdsQueue.isEmpty) return;
var (availableWidth, totalWidth, composerControllers) =
_setUpDataToSyncComposerQueue(screenWidth: screenWidth);
if (totalWidth < availableWidth) {
final currentHiddenComposerIds = hiddenComposerIds;
if (currentHiddenComposerIds.isEmpty) return;
for (var index = currentHiddenComposerIds.length - 1; index >= 0; index--) {
final newTotalWidth = totalWidth + ComposerUtils.minimizeWidth;
if (newTotalWidth > availableWidth) break;
final id = currentHiddenComposerIds.elementAt(index);
composerControllers[id]!.setScreenDisplayMode(ScreenDisplayMode.minimize);
totalWidth = newTotalWidth;
}
} else if (totalWidth > availableWidth) {
for (var id in minimizeComposerIds) {
if (id == updatedComposerId) continue;
composerControllers[id]!.setScreenDisplayMode(ScreenDisplayMode.hidden);
totalWidth -= ComposerUtils.minimizeWidth;
if (totalWidth <= availableWidth) return;
}
for (var id in normalComposerIds) {
if (id == updatedComposerId) continue;
final controller = composerControllers[id]!;
var newTotalWidth = totalWidth - (ComposerUtils.normalWidth - ComposerUtils.minimizeWidth);
if (newTotalWidth <= availableWidth) {
controller.setScreenDisplayMode(ScreenDisplayMode.minimize);
return;
}
newTotalWidth = totalWidth - ComposerUtils.normalWidth;
if (newTotalWidth <= availableWidth) {
controller.setScreenDisplayMode(ScreenDisplayMode.hidden);
return;
}
totalWidth = newTotalWidth;
}
}
}
void syncComposerStateWhenResponsiveChanged({required double screenWidth}) =>
syncComposerStateWhenComposerQueueChanged(screenWidth: screenWidth);
bool get hasComposer => composerIdsQueue.isNotEmpty;
int get countComposerHidden => composers.values
@@ -173,12 +243,31 @@ class ComposerManager extends GetxController {
.toList();
}
List<String> get displayedComposerIds {
return composerIdsQueue
.where((id) => !getComposerView(id).controller.isHiddenScreen)
.toList();
}
List<String> get minimizeComposerIds {
return composerIdsQueue
.where((id) => getComposerView(id).controller.isMinimizeScreen)
.toList();
}
List<String> get normalComposerIds {
return composerIdsQueue
.where((id) => getComposerView(id).controller.isNormalScreen)
.toList();
}
void showComposerIfHidden(String composerId) {
if (!composers.containsKey(composerId)) return;
composerIdsQueue.remove(composerId);
composerIdsQueue.add(composerId);
final composerView = getComposerView(composerId);
composerView.controller.setScreenDisplayMode(ScreenDisplayMode.normal);
_syncQueueIfNeeded();
}
ComposerView getComposerView(String id) => composers[id]!;
@@ -7,4 +7,5 @@ class ComposerUtils {
static const double composerExpandMoreButtonMaxWidth = 130;
static const double composerExpandMoreButtonMaxHeight = 52;
static const double padding = 16;
static const double space = 8;
}
@@ -27,6 +27,9 @@ class _ComposerOverlayViewState extends State<ComposerOverlayView> {
@override
Widget build(BuildContext context) {
_composerManager.syncComposerStateWhenResponsiveChanged(
screenWidth: context.width,
);
return Obx(() {
final composers = _composerManager.composers;
final composerIdsQueue = _composerManager.composerIdsQueue;
@@ -44,14 +47,6 @@ class _ComposerOverlayViewState extends State<ComposerOverlayView> {
return _composerManager.getComposerView(composerIdsQueue.first);
}
final isExceedsScreenSize = _composerManager.isExceedsScreenSize(
screenWidth: context.width,
);
if (isExceedsScreenSize) {
_composerManager.syncComposerQueue(screenWidth: context.width);
}
final countComposerHidden = _composerManager.countComposerHidden;
final visibleComposers = composerIdsQueue
.map(_composerManager.getComposerView)
@@ -60,21 +55,24 @@ class _ComposerOverlayViewState extends State<ComposerOverlayView> {
return Align(
alignment: AlignmentDirectional.bottomEnd,
child: Padding(
padding: const EdgeInsetsDirectional.all(ComposerUtils.padding),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [
if (countComposerHidden > 0)
ExpandComposerButton(
countComposerHidden: countComposerHidden,
onRemoveHiddenComposerItem: (controller) =>
controller.handleClickCloseComposer(context),
onShowComposerAction: _composerManager.showComposerIfHidden,
),
...visibleComposers,
],
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Padding(
padding: const EdgeInsetsDirectional.all(ComposerUtils.padding),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [
if (countComposerHidden > 0)
ExpandComposerButton(
countComposerHidden: countComposerHidden,
onRemoveHiddenComposerItem: (controller) =>
controller.handleClickCloseComposer(context),
onShowComposerAction: _composerManager.showComposerIfHidden,
),
...visibleComposers,
],
),
),
),
);
@@ -50,7 +50,9 @@ class DesktopAppBarComposerWidget extends StatelessWidget {
? imagePaths.icFullScreenExit
: imagePaths.icFullScreen,
backgroundColor: Colors.transparent,
tooltipMessage: AppLocalizations.of(context).fullscreen,
tooltipMessage: displayMode == ScreenDisplayMode.fullScreen
? AppLocalizations.of(context).exitFullscreen
: AppLocalizations.of(context).fullscreen,
iconSize: AppBarComposerWidgetStyle.iconSize,
iconColor: AppBarComposerWidgetStyle.iconColor,
padding: AppBarComposerWidgetStyle.iconPadding,
@@ -33,7 +33,7 @@ class HiddenComposerListViewOverlay extends StatelessWidget {
final hiddenComposerIds = composerManager.hiddenComposerIds;
final maxHeight = responsiveUtils.getSizeScreenHeight(context)
- ComposerUtils.composerExpandMoreButtonMaxHeight
- ComposerUtils.padding;
- ComposerUtils.padding * 2;
return Container(
constraints: BoxConstraints(maxHeight: maxHeight),
@@ -41,6 +41,7 @@ class HiddenComposerListViewOverlay extends StatelessWidget {
child: ListView.builder(
itemCount: hiddenComposerIds.length,
shrinkWrap: true,
padding: const EdgeInsetsDirectional.only(end: 16),
itemBuilder: (context, index) {
final composerId = hiddenComposerIds[index];
final controller = composerManager.getComposerView(composerId).controller;
+6
View File
@@ -4369,5 +4369,11 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"exitFullscreen": "Exit fullscreen",
"@exitFullscreen": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
}
}
@@ -4590,4 +4590,11 @@ class AppLocalizations {
name: 'hideAll',
);
}
String get exitFullscreen {
return Intl.message(
'Exit fullscreen',
name: 'exitFullscreen',
);
}
}