TF-4193 Show/Hide Label list when toggle label state in Setting

This commit is contained in:
dab246
2025-12-09 16:05:19 +07:00
committed by Dat H. Pham
parent 10038a3836
commit ef2ab39a3a
18 changed files with 209 additions and 24 deletions
@@ -9,6 +9,7 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:labels/model/label.dart';
import 'package:model/email/email_action_type.dart';
import 'package:model/email/presentation_email.dart';
import 'package:model/extensions/list_email_address_extension.dart';
@@ -248,9 +249,22 @@ class EmailView extends GetWidget<SingleEmailController> {
children: [
if (!isInsideThreadDetailView || isFirstEmailInThreadDetail)
Obx(() {
final allLabels =
controller.mailboxDashBoardController.labelController.labels;
final emailLabels = presentationEmail.getLabelList(allLabels);
final isLabelCapabilitySupported = controller
.mailboxDashBoardController.isLabelCapabilitySupported;
final labelController =
controller.mailboxDashBoardController.labelController;
final isLabelSettingEnabled =
labelController.isLabelSettingEnabled.isTrue;
List<Label>? emailLabels;
if (isLabelCapabilitySupported && isLabelSettingEnabled) {
emailLabels = presentationEmail.getLabelList(
labelController.labels,
);
}
return EmailSubjectWidget(
presentationEmail: presentationEmail.copyWith(
@@ -18,6 +18,8 @@ import 'package:tmail_ui_user/features/labels/domain/usecases/create_new_label_i
import 'package:tmail_ui_user/features/labels/domain/usecases/get_all_label_interactor.dart';
import 'package:tmail_ui_user/features/labels/presentation/label_interactor_bindings.dart';
import 'package:tmail_ui_user/features/labels/presentation/widgets/create_new_label_modal.dart';
import 'package:tmail_ui_user/features/manage_account/domain/state/get_label_setting_state.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_label_setting_state_interactor.dart';
import 'package:tmail_ui_user/main/error/capability_validator.dart';
import 'package:tmail_ui_user/main/exceptions/logic_exception.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
@@ -26,14 +28,31 @@ class LabelController extends BaseController {
final labels = <Label>[].obs;
final labelListExpandMode = Rx(ExpandMode.EXPAND);
final isCreateNewLabelModalVisible = RxBool(false);
final isLabelSettingEnabled = RxBool(false);
GetAllLabelInteractor? _getAllLabelInteractor;
CreateNewLabelInteractor? _createNewLabelInteractor;
GetLabelSettingStateInteractor? _getLabelSettingStateInteractor;
bool isLabelCapabilitySupported(Session session, AccountId accountId) {
return LabelsConstants.labelsCapability.isSupported(session, accountId);
}
void checkLabelSettingState(AccountId accountId) {
_getLabelSettingStateInteractor =
getBinding<GetLabelSettingStateInteractor>();
if (_getLabelSettingStateInteractor != null) {
consumeState(_getLabelSettingStateInteractor!.execute(accountId));
} else {
isLabelSettingEnabled.value = false;
_clearLabelData();
}
}
void _clearLabelData() {
labels.clear();
}
void injectLabelsBindings() {
LabelInteractorBindings().dependencies();
_getAllLabelInteractor = getBinding<GetAllLabelInteractor>();
@@ -100,12 +119,23 @@ class LabelController extends BaseController {
labels.sortByAlphabetically();
}
void _handleGetLabelSettingStateSuccess(bool isEnabled, AccountId accountId) {
isLabelSettingEnabled.value = isEnabled;
if (isEnabled) {
injectLabelsBindings();
getAllLabels(accountId);
}
}
@override
void handleSuccessViewState(Success success) {
if (success is GetAllLabelSuccess) {
labels.value = success.labels..sortByAlphabetically();
} else if (success is CreateNewLabelSuccess) {
_handleCreateNewLabelSuccess(success);
} else if (success is GetLabelSettingStateSuccess) {
_handleGetLabelSettingStateSuccess(success.isEnabled, success.accountId);
} else {
super.handleSuccessViewState(success);
}
@@ -117,6 +147,9 @@ class LabelController extends BaseController {
labels.value = [];
} else if (failure is CreateNewLabelFailure) {
_handleCreateNewLabelFailure(failure);
} else if (failure is GetLabelSettingStateFailure) {
isLabelSettingEnabled.value = false;
_clearLabelData();
} else {
super.handleFailureViewState(failure);
}
@@ -126,6 +159,7 @@ class LabelController extends BaseController {
void onClose() {
_getAllLabelInteractor = null;
_createNewLabelInteractor = null;
_getLabelSettingStateInteractor = null;
super.onClose();
}
}
@@ -346,10 +346,18 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
Widget buildLabelsBar(BuildContext context, bool isDesktop) {
return Obx(() {
if (controller.mailboxDashBoardController.isLabelCapabilitySupported) {
final labelController =
controller.mailboxDashBoardController.labelController;
final isLabelCapabilitySupported = controller
.mailboxDashBoardController
.isLabelCapabilitySupported;
final labelController =
controller.mailboxDashBoardController.labelController;
final isLabelSettingEnabled = labelController
.isLabelSettingEnabled
.isTrue;
if (isLabelCapabilitySupported && isLabelSettingEnabled) {
final accountId = controller.accountId;
final labelListExpandMode = labelController.labelListExpandMode.value;
final countLabels = labelController.labels.length;
@@ -376,10 +384,18 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
Widget buildLabelsList(BuildContext context, bool isDesktop) {
return Obx(() {
if (controller.mailboxDashBoardController.isLabelCapabilitySupported) {
final labelController =
controller.mailboxDashBoardController.labelController;
final isLabelCapabilitySupported = controller
.mailboxDashBoardController
.isLabelCapabilitySupported;
final labelController =
controller.mailboxDashBoardController.labelController;
final isLabelSettingEnabled = labelController
.isLabelSettingEnabled
.isTrue;
if (isLabelCapabilitySupported && isLabelSettingEnabled) {
final labelListExpandMode = labelController.labelListExpandMode.value;
final labels = labelController.labels;
@@ -909,8 +909,7 @@ class MailboxDashBoardController extends ReloadableController
);
if (isLabelCapabilitySupported) {
labelController.injectLabelsBindings();
labelController.getAllLabels(currentAccountId);
labelController.checkLabelSettingState(currentAccountId);
}
}
@@ -2087,6 +2086,9 @@ class MailboxDashBoardController extends ReloadableController
getServerSetting();
spamReportController.getSpamReportStateAction();
loadAIScribeConfig();
if (isLabelCapabilitySupported && accountId.value != null) {
labelController.checkLabelSettingState(accountId.value!);
}
}
Future<List<PresentationEmail>> quickSearchEmails(String query) async {
@@ -2164,6 +2166,9 @@ class MailboxDashBoardController extends ReloadableController
getServerSetting();
spamReportController.getSpamReportStateAction();
loadAIScribeConfig();
if (isLabelCapabilitySupported && accountId.value != null) {
labelController.checkLabelSettingState(accountId.value!);
}
}
void _handleUpdateVacationSuccess(UpdateVacationSuccess success) {
@@ -16,4 +16,6 @@ abstract class ManageAccountDataSource {
Future<bool> getLabelVisibility();
Future<void> saveLabelVisibility(bool visible);
Future<bool> getLabelSettingState();
}
@@ -5,6 +5,7 @@ import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_
import 'package:tmail_ui_user/features/manage_account/data/local/preferences_setting_manager.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/ai_scribe_config.dart';
import 'package:tmail_ui_user/features/manage_account/data/local/setting_cache_manager.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/label_config.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_setting.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/spam_report_config.dart';
@@ -52,6 +53,10 @@ class ManageAccountDataSourceImpl extends ManageAccountDataSource {
await _preferencesSettingManager.updateAIScribe(
preferencesConfig.isEnabled,
);
} else if (preferencesConfig is LabelConfig) {
await _preferencesSettingManager.updateLabel(
preferencesConfig.isEnabled,
);
} else {
await _preferencesSettingManager.savePreferences(
preferencesConfig,
@@ -94,4 +99,15 @@ class ManageAccountDataSourceImpl extends ManageAccountDataSource {
throw error;
});
}
@override
Future<bool> getLabelSettingState() {
return Future.sync(() async {
final labelConfig = await _preferencesSettingManager.getLabelConfig();
return labelConfig.isEnabled;
}).catchError((error, stackTrace) async {
await _exceptionThrower.throwException(error, stackTrace);
throw error;
});
}
}
@@ -65,7 +65,7 @@ class PreferencesSettingManager {
return PreferencesSetting(listConfigs);
}
String _getPreferencesConfig(PreferencesConfig config) {
String _getPreferencesConfigKey(PreferencesConfig config) {
if (config is ThreadDetailConfig) {
return _preferencesSettingThreadKey;
} else if (config is SpamReportConfig) {
@@ -83,7 +83,7 @@ class PreferencesSettingManager {
Future<void> savePreferences(PreferencesConfig config) async {
await _sharedPreferences.setString(
_getPreferencesConfig(config),
_getPreferencesConfigKey(config),
jsonEncode(config.toJson()),
);
}
@@ -41,4 +41,9 @@ class ManageAccountRepositoryImpl extends ManageAccountRepository {
Future<void> saveLabelVisibility(bool visible) {
return dataSource.saveLabelVisibility(visible);
}
@override
Future<bool> getLabelSettingState() {
return dataSource.getLabelSettingState();
}
}
@@ -16,4 +16,6 @@ abstract class ManageAccountRepository {
Future<bool> getLabelVisibility();
Future<void> saveLabelVisibility(bool visible);
Future<bool> getLabelSettingState();
}
@@ -0,0 +1,19 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
class GettingLabelSettingState extends LoadingState {}
class GetLabelSettingStateSuccess extends UIState {
final bool isEnabled;
final AccountId accountId;
GetLabelSettingStateSuccess(this.isEnabled, this.accountId);
@override
List<Object> get props => [isEnabled, accountId];
}
class GetLabelSettingStateFailure extends FeatureFailure {
GetLabelSettingStateFailure(dynamic exception) : super(exception: exception);
}
@@ -0,0 +1,22 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:tmail_ui_user/features/manage_account/domain/repository/manage_account_repository.dart';
import 'package:tmail_ui_user/features/manage_account/domain/state/get_label_setting_state.dart';
class GetLabelSettingStateInteractor {
final ManageAccountRepository _manageAccountRepository;
GetLabelSettingStateInteractor(this._manageAccountRepository);
Stream<Either<Failure, Success>> execute(AccountId accountId) async* {
try {
yield Right(GettingLabelSettingState());
final isEnable = await _manageAccountRepository.getLabelSettingState();
yield Right(GetLabelSettingStateSuccess(isEnable, accountId));
} catch (e) {
yield Left(GetLabelSettingStateFailure(e));
}
}
}
@@ -7,6 +7,7 @@ import 'package:tmail_ui_user/features/manage_account/data/local/preferences_set
import 'package:tmail_ui_user/features/manage_account/data/local/setting_cache_manager.dart';
import 'package:tmail_ui_user/features/manage_account/data/repository/manage_account_repository_impl.dart';
import 'package:tmail_ui_user/features/manage_account/domain/repository/manage_account_repository.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_label_setting_state_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_label_visibility_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/save_label_visibility_interactor.dart';
import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart';
@@ -39,6 +40,9 @@ class SettingInteractorBindings extends InteractorsBindings {
Get.lazyPut(
() => GetLabelVisibilityInteractor(Get.find<ManageAccountRepository>()),
);
Get.lazyPut(
() => GetLabelSettingStateInteractor(Get.find<ManageAccountRepository>()),
);
}
@override
@@ -8,6 +8,7 @@ import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/loader_status.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/ai_scribe_config.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/label_config.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_setting.dart';
import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/spam_report_config.dart';
@@ -162,6 +163,9 @@ class PreferencesController extends BaseController {
case PreferencesOptionType.aiScribe:
config = AIScribeConfig(isEnabled: !isEnabled);
break;
case PreferencesOptionType.label:
config = LabelConfig(isEnabled: !isEnabled);
break;
default:
break;
}
@@ -12,6 +12,7 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:labels/model/label.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/base/widget/keyboard/keyboard_handler_wrapper.dart';
@@ -732,9 +733,20 @@ class SearchEmailView extends GetWidget<SearchEmailController>
final isAINeedsActionEnabled = dashboardController.isAINeedsActionEnabled;
final allLabels = dashboardController.labelController.labels;
final isLabelCapabilitySupported = dashboardController.isLabelCapabilitySupported;
final emailLabels = presentationEmail.getLabelList(allLabels);
final labelController = dashboardController.labelController;
final isLabelSettingEnabled =
labelController.isLabelSettingEnabled.isTrue;
List<Label>? emailLabels;
if (isLabelCapabilitySupported && isLabelSettingEnabled) {
emailLabels = presentationEmail.getLabelList(
labelController.labels,
);
}
return EmailTileBuilder(
presentationEmail: presentationEmail,
@@ -5,6 +5,7 @@ import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:labels/model/label.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/base/mixin/popup_menu_widget_mixin.dart';
@@ -623,9 +624,22 @@ class ThreadView extends GetWidget<ThreadController>
direction,
),
child: Obx(() {
final allLabels =
controller.mailboxDashBoardController.labelController.labels;
final emailLabels = presentationEmail.getLabelList(allLabels);
final isLabelCapabilitySupported = controller
.mailboxDashBoardController.isLabelCapabilitySupported;
final labelController =
controller.mailboxDashBoardController.labelController;
final isLabelSettingEnabled =
labelController.isLabelSettingEnabled.isTrue;
List<Label>? emailLabels;
if (isLabelCapabilitySupported && isLabelSettingEnabled) {
emailLabels = presentationEmail.getLabelList(
labelController.labels,
);
}
return EmailTileBuilder(
key: Key('email_tile_builder_${presentationEmail.id?.asString}'),
@@ -1,5 +1,6 @@
import 'package:core/utils/platform_info.dart';
import 'package:flutter/material.dart';
import 'package:labels/model/label.dart';
import 'package:model/email/email_in_thread_status.dart';
import 'package:model/extensions/presentation_email_extension.dart';
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
@@ -15,7 +16,7 @@ import 'package:tmail_ui_user/features/thread_detail/presentation/widgets/thread
import 'package:tmail_ui_user/features/thread_detail/presentation/widgets/thread_detail_load_more_circle.dart';
extension GetThreadDetailEmailViews on ThreadDetailController {
List<Widget> getThreadDetailEmailViews() {
List<Widget> getThreadDetailEmailViews({List<Label>? labels}) {
final loadMoreSegments = Map<LoadMoreIndex, LoadMoreCount>.from(this.loadMoreSegments);
return emailIdsPresentation.entries.map((entry) {
@@ -45,9 +46,8 @@ extension GetThreadDetailEmailViews on ThreadDetailController {
final isFirstEmailInThreadDetail = indexOfEmailId == 0;
if (presentationEmail.emailInThreadStatus == EmailInThreadStatus.collapsed) {
final allLabels = mailboxDashBoardController.labelController.labels;
final emailLabels = isFirstEmailInThreadDetail
? emailIdsPresentation.values.last?.getLabelList(allLabels)
final emailLabels = labels?.isNotEmpty == true && isFirstEmailInThreadDetail
? emailIdsPresentation.values.last?.getLabelList(labels!)
: null;
return ThreadDetailCollapsedEmail(
@@ -17,8 +17,8 @@ import 'package:tmail_ui_user/features/thread_detail/domain/state/get_thread_by_
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/close_thread_detail_action.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/get_thread_detail_action_status.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/get_thread_details_email_views.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/on_thread_detail_action_click.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_mail_shortcut_actions_extension.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/on_thread_detail_action_click.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/on_thread_page_changed.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/parsing_email_opened_properties_extension.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
@@ -101,7 +101,18 @@ class ThreadDetailView extends GetWidget<ThreadDetailController> {
}
}),
Obx(() {
final threadChildren = controller.getThreadDetailEmailViews();
final isLabelCapabilitySupported = controller
.mailboxDashBoardController.isLabelCapabilitySupported;
final labelController =
controller.mailboxDashBoardController.labelController;
final isLabelSettingEnabled =
labelController.isLabelSettingEnabled.isTrue;
final threadChildren = isLabelCapabilitySupported && isLabelSettingEnabled
? controller.getThreadDetailEmailViews(labels: labelController.labels)
: controller.getThreadDetailEmailViews();
late Widget threadBody;
@@ -457,6 +457,7 @@ void main() {
when(mailboxDashboardController.spamReportController.spamReportState).thenReturn(Rx(SpamReportState.disabled));
when(mailboxDashboardController.spamReportController.presentationSpamMailbox).thenReturn(Rxn(null));
when(mailboxDashboardController.downloadController.listDownloadTaskState).thenReturn(RxList([]));
when(mailboxDashboardController.labelController.isLabelSettingEnabled).thenReturn(RxBool(false));
when(mailboxDashboardController.labelController.labels).thenReturn(RxList([]));
when(composerManager.composers).thenReturn(RxMap({}));
@@ -534,6 +535,7 @@ void main() {
when(mailboxDashboardController.spamReportController.spamReportState).thenReturn(Rx(SpamReportState.disabled));
when(mailboxDashboardController.spamReportController.presentationSpamMailbox).thenReturn(Rxn(null));
when(mailboxDashboardController.downloadController.listDownloadTaskState).thenReturn(RxList([]));
when(mailboxDashboardController.labelController.isLabelSettingEnabled).thenReturn(RxBool(false));
when(mailboxDashboardController.labelController.labels).thenReturn(RxList([]));
when(composerManager.composers).thenReturn(RxMap({}));
@@ -598,6 +600,7 @@ void main() {
when(mailboxDashboardController.spamReportController.spamReportState).thenReturn(Rx(SpamReportState.disabled));
when(mailboxDashboardController.spamReportController.presentationSpamMailbox).thenReturn(Rxn(null));
when(mailboxDashboardController.downloadController.listDownloadTaskState).thenReturn(RxList([]));
when(mailboxDashboardController.labelController.isLabelSettingEnabled).thenReturn(RxBool(false));
when(mailboxDashboardController.labelController.labels).thenReturn(RxList([]));
when(composerManager.composers).thenReturn(RxMap({}));
@@ -659,6 +662,7 @@ void main() {
when(mailboxDashboardController.spamReportController.spamReportState).thenReturn(Rx(SpamReportState.disabled));
when(mailboxDashboardController.spamReportController.presentationSpamMailbox).thenReturn(Rxn(null));
when(mailboxDashboardController.downloadController.listDownloadTaskState).thenReturn(RxList([]));
when(mailboxDashboardController.labelController.isLabelSettingEnabled).thenReturn(RxBool(false));
when(mailboxDashboardController.labelController.labels).thenReturn(RxList([]));
when(composerManager.composers).thenReturn(RxMap({}));
@@ -716,6 +720,7 @@ void main() {
when(mailboxDashboardController.spamReportController.spamReportState).thenReturn(Rx(SpamReportState.disabled));
when(mailboxDashboardController.spamReportController.presentationSpamMailbox).thenReturn(Rxn(null));
when(mailboxDashboardController.downloadController.listDownloadTaskState).thenReturn(RxList([]));
when(mailboxDashboardController.labelController.isLabelSettingEnabled).thenReturn(RxBool(false));
when(mailboxDashboardController.labelController.labels).thenReturn(RxList([]));
when(composerManager.composers).thenReturn(RxMap({}));