TF-4178 Implement create new label
This commit is contained in:
@@ -8,6 +8,7 @@ class ModalListActionButtonWidget extends StatelessWidget {
|
|||||||
final VoidCallback onNegativeAction;
|
final VoidCallback onNegativeAction;
|
||||||
final VoidCallback onPositiveAction;
|
final VoidCallback onPositiveAction;
|
||||||
final EdgeInsetsGeometry? padding;
|
final EdgeInsetsGeometry? padding;
|
||||||
|
final bool isPositiveActionEnabled;
|
||||||
|
|
||||||
const ModalListActionButtonWidget({
|
const ModalListActionButtonWidget({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -15,6 +16,7 @@ class ModalListActionButtonWidget extends StatelessWidget {
|
|||||||
required this.negativeLabel,
|
required this.negativeLabel,
|
||||||
required this.onPositiveAction,
|
required this.onPositiveAction,
|
||||||
required this.onNegativeAction,
|
required this.onNegativeAction,
|
||||||
|
this.isPositiveActionEnabled = true,
|
||||||
this.padding,
|
this.padding,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -34,9 +36,13 @@ class ModalListActionButtonWidget extends StatelessWidget {
|
|||||||
height: 48,
|
height: 48,
|
||||||
child: ConfirmDialogButton(
|
child: ConfirmDialogButton(
|
||||||
label: positiveLabel,
|
label: positiveLabel,
|
||||||
backgroundColor: AppColor.primaryMain,
|
backgroundColor: isPositiveActionEnabled
|
||||||
textColor: Colors.white,
|
? AppColor.primaryMain
|
||||||
onTapAction: onPositiveAction,
|
: AppColor.profileMenuDivider.withValues(alpha: 0.12),
|
||||||
|
textColor: isPositiveActionEnabled
|
||||||
|
? Colors.white
|
||||||
|
: AppColor.m3SurfaceBackground.withValues(alpha: 0.38),
|
||||||
|
onTapAction: isPositiveActionEnabled ? onPositiveAction : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -79,9 +79,13 @@ mixin HandleSetErrorMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parseErrorForSetResponse(SetResponse? response, Id requestId) {
|
parseErrorForSetResponse(SetResponse? response, Id requestId) {
|
||||||
final mapError =
|
final mapError = <Id, SetError>{
|
||||||
response?.notCreated ?? response?.notUpdated ?? response?.notDestroyed;
|
...?response?.notCreated,
|
||||||
if (mapError != null && mapError.containsKey(requestId)) {
|
...?response?.notUpdated,
|
||||||
|
...?response?.notDestroyed,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (mapError.containsKey(requestId)) {
|
||||||
final setError = mapError[requestId];
|
final setError = mapError[requestId];
|
||||||
log('HandleSetErrorMixin::parseErrorForSetResponse():setError: $setError');
|
log('HandleSetErrorMixin::parseErrorForSetResponse():setError: $setError');
|
||||||
if (setError?.type == ErrorMethodResponse.invalidArguments) {
|
if (setError?.type == ErrorMethodResponse.invalidArguments) {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import 'package:core/presentation/state/failure.dart';
|
import 'package:core/presentation/state/failure.dart';
|
||||||
import 'package:core/presentation/state/success.dart';
|
import 'package:core/presentation/state/success.dart';
|
||||||
|
import 'package:core/utils/app_logger.dart';
|
||||||
import 'package:core/utils/platform_info.dart';
|
import 'package:core/utils/platform_info.dart';
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||||
@@ -9,11 +11,15 @@ import 'package:labels/model/label.dart';
|
|||||||
import 'package:labels/utils/labels_constants.dart';
|
import 'package:labels/utils/labels_constants.dart';
|
||||||
import 'package:model/mailbox/expand_mode.dart';
|
import 'package:model/mailbox/expand_mode.dart';
|
||||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
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/labels/domain/state/create_new_label_state.dart';
|
||||||
import 'package:tmail_ui_user/features/labels/domain/state/get_all_label_state.dart';
|
import 'package:tmail_ui_user/features/labels/domain/state/get_all_label_state.dart';
|
||||||
|
import 'package:tmail_ui_user/features/labels/domain/usecases/create_new_label_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/labels/domain/usecases/get_all_label_interactor.dart';
|
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/label_interactor_bindings.dart';
|
||||||
import 'package:tmail_ui_user/features/labels/presentation/widgets/create_new_label_modal.dart';
|
import 'package:tmail_ui_user/features/labels/presentation/widgets/create_new_label_modal.dart';
|
||||||
import 'package:tmail_ui_user/main/error/capability_validator.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';
|
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||||
|
|
||||||
class LabelController extends BaseController {
|
class LabelController extends BaseController {
|
||||||
@@ -22,6 +28,7 @@ class LabelController extends BaseController {
|
|||||||
final isCreateNewLabelModalVisible = RxBool(false);
|
final isCreateNewLabelModalVisible = RxBool(false);
|
||||||
|
|
||||||
GetAllLabelInteractor? _getAllLabelInteractor;
|
GetAllLabelInteractor? _getAllLabelInteractor;
|
||||||
|
CreateNewLabelInteractor? _createNewLabelInteractor;
|
||||||
|
|
||||||
bool isLabelCapabilitySupported(Session session, AccountId accountId) {
|
bool isLabelCapabilitySupported(Session session, AccountId accountId) {
|
||||||
return LabelsConstants.labelsCapability.isSupported(session, accountId);
|
return LabelsConstants.labelsCapability.isSupported(session, accountId);
|
||||||
@@ -30,6 +37,7 @@ class LabelController extends BaseController {
|
|||||||
void injectLabelsBindings() {
|
void injectLabelsBindings() {
|
||||||
LabelInteractorBindings().dependencies();
|
LabelInteractorBindings().dependencies();
|
||||||
_getAllLabelInteractor = getBinding<GetAllLabelInteractor>();
|
_getAllLabelInteractor = getBinding<GetAllLabelInteractor>();
|
||||||
|
_createNewLabelInteractor = getBinding<CreateNewLabelInteractor>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void getAllLabels(AccountId accountId) {
|
void getAllLabels(AccountId accountId) {
|
||||||
@@ -44,7 +52,7 @@ class LabelController extends BaseController {
|
|||||||
: ExpandMode.COLLAPSE;
|
: ExpandMode.COLLAPSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> openCreateNewLabelModal() async {
|
Future<void> openCreateNewLabelModal(AccountId? accountId) async {
|
||||||
if (PlatformInfo.isWeb) {
|
if (PlatformInfo.isWeb) {
|
||||||
isCreateNewLabelModalVisible.value = true;
|
isCreateNewLabelModalVisible.value = true;
|
||||||
}
|
}
|
||||||
@@ -52,7 +60,10 @@ class LabelController extends BaseController {
|
|||||||
await Get.generalDialog(
|
await Get.generalDialog(
|
||||||
barrierDismissible: true,
|
barrierDismissible: true,
|
||||||
barrierLabel: 'create-new-label-modal',
|
barrierLabel: 'create-new-label-modal',
|
||||||
pageBuilder: (_, __, ___) => CreateNewLabelModal(labels: labels),
|
pageBuilder: (_, __, ___) => CreateNewLabelModal(
|
||||||
|
labels: labels,
|
||||||
|
onCreateNewLabelCallback: (label) => _createNewLabel(accountId, label),
|
||||||
|
),
|
||||||
).whenComplete(() {
|
).whenComplete(() {
|
||||||
if (PlatformInfo.isWeb) {
|
if (PlatformInfo.isWeb) {
|
||||||
isCreateNewLabelModalVisible.value = false;
|
isCreateNewLabelModalVisible.value = false;
|
||||||
@@ -60,10 +71,41 @@ class LabelController extends BaseController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _createNewLabel(AccountId? accountId, Label label) {
|
||||||
|
log('LabelController::_createNewLabel:Label: $label');
|
||||||
|
if (accountId == null) {
|
||||||
|
consumeState(
|
||||||
|
Stream.value(Left(CreateNewLabelFailure(NotFoundAccountIdException()))),
|
||||||
|
);
|
||||||
|
} else if (_createNewLabelInteractor == null) {
|
||||||
|
consumeState(
|
||||||
|
Stream.value(Left(CreateNewLabelFailure(InteractorNotInitialized()))),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
consumeState(_createNewLabelInteractor!.execute(accountId, label));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleCreateNewLabelSuccess(CreateNewLabelSuccess success) {
|
||||||
|
toastManager.showMessageSuccess(success);
|
||||||
|
_addLabelToList(success.newLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleCreateNewLabelFailure(CreateNewLabelFailure failure) {
|
||||||
|
toastManager.showMessageFailure(failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _addLabelToList(Label newLabel) {
|
||||||
|
labels.add(newLabel);
|
||||||
|
labels.sortByAlphabetically();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void handleSuccessViewState(Success success) {
|
void handleSuccessViewState(Success success) {
|
||||||
if (success is GetAllLabelSuccess) {
|
if (success is GetAllLabelSuccess) {
|
||||||
labels.value = success.labels..sortByAlphabetically();
|
labels.value = success.labels..sortByAlphabetically();
|
||||||
|
} else if (success is CreateNewLabelSuccess) {
|
||||||
|
_handleCreateNewLabelSuccess(success);
|
||||||
} else {
|
} else {
|
||||||
super.handleSuccessViewState(success);
|
super.handleSuccessViewState(success);
|
||||||
}
|
}
|
||||||
@@ -73,6 +115,8 @@ class LabelController extends BaseController {
|
|||||||
void handleFailureViewState(Failure failure) {
|
void handleFailureViewState(Failure failure) {
|
||||||
if (failure is GetAllLabelFailure) {
|
if (failure is GetAllLabelFailure) {
|
||||||
labels.value = [];
|
labels.value = [];
|
||||||
|
} else if (failure is CreateNewLabelFailure) {
|
||||||
|
_handleCreateNewLabelFailure(failure);
|
||||||
} else {
|
} else {
|
||||||
super.handleFailureViewState(failure);
|
super.handleFailureViewState(failure);
|
||||||
}
|
}
|
||||||
@@ -81,6 +125,7 @@ class LabelController extends BaseController {
|
|||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
_getAllLabelInteractor = null;
|
_getAllLabelInteractor = null;
|
||||||
|
_createNewLabelInteractor = null;
|
||||||
super.onClose();
|
super.onClose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:tmail_ui_user/features/labels/data/datasource_impl/label_datasou
|
|||||||
import 'package:tmail_ui_user/features/labels/data/network/label_api.dart';
|
import 'package:tmail_ui_user/features/labels/data/network/label_api.dart';
|
||||||
import 'package:tmail_ui_user/features/labels/data/repository/label_repository_impl.dart';
|
import 'package:tmail_ui_user/features/labels/data/repository/label_repository_impl.dart';
|
||||||
import 'package:tmail_ui_user/features/labels/domain/repository/label_repository.dart';
|
import 'package:tmail_ui_user/features/labels/domain/repository/label_repository.dart';
|
||||||
|
import 'package:tmail_ui_user/features/labels/domain/usecases/create_new_label_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/labels/domain/usecases/get_all_label_interactor.dart';
|
import 'package:tmail_ui_user/features/labels/domain/usecases/get_all_label_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
|
import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
|
||||||
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
|
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
|
||||||
@@ -31,6 +32,7 @@ class LabelInteractorBindings extends InteractorsBindings {
|
|||||||
@override
|
@override
|
||||||
void bindingsInteractor() {
|
void bindingsInteractor() {
|
||||||
Get.lazyPut(() => GetAllLabelInteractor(Get.find<LabelRepository>()));
|
Get.lazyPut(() => GetAllLabelInteractor(Get.find<LabelRepository>()));
|
||||||
|
Get.lazyPut(() => CreateNewLabelInteractor(Get.find<LabelRepository>()));
|
||||||
Get.lazyPut(() => VerifyNameInteractor());
|
Get.lazyPut(() => VerifyNameInteractor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,13 +11,11 @@ import 'package:core/presentation/views/dialog/modal_list_action_button_widget.d
|
|||||||
import 'package:core/utils/platform_info.dart';
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:labels/extensions/list_label_extension.dart';
|
import 'package:labels/labels.dart';
|
||||||
import 'package:labels/model/label.dart';
|
|
||||||
import 'package:tmail_ui_user/features/base/widget/label_input_field_builder.dart';
|
import 'package:tmail_ui_user/features/base/widget/label_input_field_builder.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/duplicate_name_validator.dart';
|
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/duplicate_name_validator.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/empty_name_validator.dart';
|
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/empty_name_validator.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/name_with_space_only_validator.dart';
|
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/name_with_space_only_validator.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/special_character_validator.dart';
|
|
||||||
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/validator.dart';
|
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/validator.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_creator/domain/state/verify_name_view_state.dart';
|
import 'package:tmail_ui_user/features/mailbox_creator/domain/state/verify_name_view_state.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
|
import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
|
||||||
@@ -25,10 +23,17 @@ import 'package:tmail_ui_user/features/mailbox_creator/presentation/extensions/v
|
|||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||||
|
|
||||||
|
typedef OnCreateNewLabelCallback = Function(Label label);
|
||||||
|
|
||||||
class CreateNewLabelModal extends StatefulWidget {
|
class CreateNewLabelModal extends StatefulWidget {
|
||||||
final List<Label> labels;
|
final List<Label> labels;
|
||||||
|
final OnCreateNewLabelCallback onCreateNewLabelCallback;
|
||||||
|
|
||||||
const CreateNewLabelModal({super.key, required this.labels});
|
const CreateNewLabelModal({
|
||||||
|
super.key,
|
||||||
|
required this.labels,
|
||||||
|
required this.onCreateNewLabelCallback,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CreateNewLabelModal> createState() => _CreateNewLabelModalState();
|
State<CreateNewLabelModal> createState() => _CreateNewLabelModalState();
|
||||||
@@ -41,6 +46,7 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
|||||||
final ValueNotifier<String?> _labelNameErrorTextNotifier =
|
final ValueNotifier<String?> _labelNameErrorTextNotifier =
|
||||||
ValueNotifier(null);
|
ValueNotifier(null);
|
||||||
final ValueNotifier<Color?> _labelSelectedColorNotifier = ValueNotifier(null);
|
final ValueNotifier<Color?> _labelSelectedColorNotifier = ValueNotifier(null);
|
||||||
|
final ValueNotifier<bool> _createLabelStateNotifier = ValueNotifier(false);
|
||||||
final TextEditingController _nameInputController = TextEditingController();
|
final TextEditingController _nameInputController = TextEditingController();
|
||||||
final FocusNode _nameInputFocusNode = FocusNode();
|
final FocusNode _nameInputFocusNode = FocusNode();
|
||||||
|
|
||||||
@@ -203,12 +209,20 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ModalListActionButtonWidget(
|
ValueListenableBuilder(
|
||||||
positiveLabel: appLocalizations.createLabel,
|
valueListenable: _createLabelStateNotifier,
|
||||||
negativeLabel: appLocalizations.cancel,
|
builder: (_, value, __) {
|
||||||
padding: const EdgeInsets.symmetric(vertical: 25),
|
return ModalListActionButtonWidget(
|
||||||
onPositiveAction: _onCreateNewLabel,
|
positiveLabel: appLocalizations.createLabel,
|
||||||
onNegativeAction: _onCloseModal,
|
negativeLabel: appLocalizations.cancel,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 25,
|
||||||
|
),
|
||||||
|
isPositiveActionEnabled: value,
|
||||||
|
onPositiveAction: _onCreateNewLabel,
|
||||||
|
onNegativeAction: _onCloseModal,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -248,10 +262,9 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
|||||||
AppLocalizations appLocalizations,
|
AppLocalizations appLocalizations,
|
||||||
String value,
|
String value,
|
||||||
) {
|
) {
|
||||||
_labelNameErrorTextNotifier.value = _verifyLabelName(
|
final errorText = _verifyLabelName(appLocalizations, value);
|
||||||
appLocalizations,
|
_labelNameErrorTextNotifier.value = errorText;
|
||||||
value,
|
_createLabelStateNotifier.value = errorText == null;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String? _verifyLabelName(AppLocalizations appLocalizations, String value) {
|
String? _verifyLabelName(AppLocalizations appLocalizations, String value) {
|
||||||
@@ -272,7 +285,6 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
|||||||
EmptyNameValidator(),
|
EmptyNameValidator(),
|
||||||
NameWithSpaceOnlyValidator(),
|
NameWithSpaceOnlyValidator(),
|
||||||
DuplicateNameValidator(_labelDisplayNameList),
|
DuplicateNameValidator(_labelDisplayNameList),
|
||||||
SpecialCharacterValidator(),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
void _clearInputFocus() {
|
void _clearInputFocus() {
|
||||||
@@ -281,6 +293,15 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
|||||||
|
|
||||||
void _onCreateNewLabel() {
|
void _onCreateNewLabel() {
|
||||||
_clearInputFocus();
|
_clearInputFocus();
|
||||||
|
|
||||||
|
final newLabel = Label(
|
||||||
|
displayName: _nameInputController.text,
|
||||||
|
color: _selectedColor != null
|
||||||
|
? HexColor(_selectedColor!.toHexTriplet())
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
widget.onCreateNewLabelCallback(newLabel);
|
||||||
|
|
||||||
popBack();
|
popBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,6 +339,7 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
|||||||
_nameInputController.dispose();
|
_nameInputController.dispose();
|
||||||
_labelNameErrorTextNotifier.dispose();
|
_labelNameErrorTextNotifier.dispose();
|
||||||
_labelSelectedColorNotifier.dispose();
|
_labelSelectedColorNotifier.dispose();
|
||||||
|
_createLabelStateNotifier.dispose();
|
||||||
_labelDisplayNameList = [];
|
_labelDisplayNameList = [];
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,6 +350,7 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
|
|||||||
final labelController =
|
final labelController =
|
||||||
controller.mailboxDashBoardController.labelController;
|
controller.mailboxDashBoardController.labelController;
|
||||||
|
|
||||||
|
final accountId = controller.accountId;
|
||||||
final labelListExpandMode = labelController.labelListExpandMode.value;
|
final labelListExpandMode = labelController.labelListExpandMode.value;
|
||||||
final countLabels = labelController.labels.length;
|
final countLabels = labelController.labels.length;
|
||||||
|
|
||||||
@@ -364,7 +365,8 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
|
|||||||
expandMode: labelListExpandMode,
|
expandMode: labelListExpandMode,
|
||||||
countLabels: countLabels,
|
countLabels: countLabels,
|
||||||
onToggleLabelListState: labelController.toggleLabelListState,
|
onToggleLabelListState: labelController.toggleLabelListState,
|
||||||
onAddNewLabel: labelController.openCreateNewLabelModal,
|
onAddNewLabel: () =>
|
||||||
|
labelController.openCreateNewLabelModal(accountId),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ extension ValicatorFailureExtension on VerifyNameFailure {
|
|||||||
return appLocalizations.this_field_cannot_be_blank;
|
return appLocalizations.this_field_cannot_be_blank;
|
||||||
} else if (exception is DuplicatedNameException) {
|
} else if (exception is DuplicatedNameException) {
|
||||||
return appLocalizations.tagNameAlreadyExists;
|
return appLocalizations.tagNameAlreadyExists;
|
||||||
} else if (exception is SpecialCharacterException) {
|
|
||||||
return appLocalizations.tagNameCannotContainSpecialCharacters;
|
|
||||||
} else if (exception is NameWithSpaceOnlyException) {
|
} else if (exception is NameWithSpaceOnlyException) {
|
||||||
return appLocalizations.thisFieldCannotContainOnlySpaces;
|
return appLocalizations.thisFieldCannotContainOnlySpaces;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -5232,12 +5232,6 @@
|
|||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"tagNameCannotContainSpecialCharacters": "Tag name cannot contain special characters",
|
|
||||||
"@tagNameCannotContainSpecialCharacters": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders_order": [],
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"tagNameAlreadyExists": "A tag with this name already exists. Please choose a different name.",
|
"tagNameAlreadyExists": "A tag with this name already exists. Please choose a different name.",
|
||||||
"@tagNameAlreadyExists": {
|
"@tagNameAlreadyExists": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -5255,5 +5249,21 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"createLabelSuccessfullyMessage": "You successfully created {labelName} label",
|
||||||
|
"@createLabelSuccessfullyMessage": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [
|
||||||
|
"labelName"
|
||||||
|
],
|
||||||
|
"placeholders": {
|
||||||
|
"labelName": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"createNewLabelFailure": "Create new label failure",
|
||||||
|
"@createNewLabelFailure": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
class InteractorNotInitialized implements Exception {}
|
||||||
@@ -5556,13 +5556,6 @@ class AppLocalizations {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String get tagNameCannotContainSpecialCharacters {
|
|
||||||
return Intl.message(
|
|
||||||
'Tag name cannot contain special characters',
|
|
||||||
name: 'tagNameCannotContainSpecialCharacters',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
String get tagNameAlreadyExists {
|
String get tagNameAlreadyExists {
|
||||||
return Intl.message(
|
return Intl.message(
|
||||||
'A tag with this name already exists. Please choose a different name.',
|
'A tag with this name already exists. Please choose a different name.',
|
||||||
@@ -5583,4 +5576,19 @@ class AppLocalizations {
|
|||||||
name: 'chooseAColourForThisLabel',
|
name: 'chooseAColourForThisLabel',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String createLabelSuccessfullyMessage(String labelName) {
|
||||||
|
return Intl.message(
|
||||||
|
'You successfully created $labelName label',
|
||||||
|
name: 'createLabelSuccessfullyMessage',
|
||||||
|
args: [labelName],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get createNewLabelFailure {
|
||||||
|
return Intl.message(
|
||||||
|
'Create new label failure',
|
||||||
|
name: 'createNewLabelFailure',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import 'package:flutter_svg/svg.dart';
|
|||||||
import 'package:jmap_dart_client/jmap/core/error/method/error_method_response.dart';
|
import 'package:jmap_dart_client/jmap/core/error/method/error_method_response.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/error/method/exception/error_method_response_exception.dart';
|
import 'package:jmap_dart_client/jmap/core/error/method/exception/error_method_response_exception.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/error/set_error.dart';
|
import 'package:jmap_dart_client/jmap/core/error/set_error.dart';
|
||||||
|
import 'package:labels/extensions/label_extension.dart';
|
||||||
import 'package:model/email/email_action_type.dart';
|
import 'package:model/email/email_action_type.dart';
|
||||||
import 'package:model/email/mark_star_action.dart';
|
import 'package:model/email/mark_star_action.dart';
|
||||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||||
@@ -27,6 +28,7 @@ import 'package:tmail_ui_user/features/download/domain/state/parse_email_by_blob
|
|||||||
import 'package:tmail_ui_user/features/download/domain/state/preview_email_from_eml_file_state.dart';
|
import 'package:tmail_ui_user/features/download/domain/state/preview_email_from_eml_file_state.dart';
|
||||||
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
|
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
|
||||||
import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart';
|
import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart';
|
||||||
|
import 'package:tmail_ui_user/features/labels/domain/state/create_new_label_state.dart';
|
||||||
import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart';
|
import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart';
|
||||||
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
|
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
|
||||||
import 'package:tmail_ui_user/features/login/domain/exceptions/oauth_authorization_error.dart';
|
import 'package:tmail_ui_user/features/login/domain/exceptions/oauth_authorization_error.dart';
|
||||||
@@ -196,6 +198,9 @@ class ToastManager {
|
|||||||
} else if (failure is MoveFolderContentFailure) {
|
} else if (failure is MoveFolderContentFailure) {
|
||||||
message = message ??
|
message = message ??
|
||||||
appLocalizations.moveFolderContentToastMessage;
|
appLocalizations.moveFolderContentToastMessage;
|
||||||
|
} else if (failure is CreateNewLabelFailure) {
|
||||||
|
message = message ??
|
||||||
|
appLocalizations.createNewLabelFailure;
|
||||||
}
|
}
|
||||||
log('ToastManager::showMessageFailure: Message: $message');
|
log('ToastManager::showMessageFailure: Message: $message');
|
||||||
if (message?.trim().isNotEmpty == true) {
|
if (message?.trim().isNotEmpty == true) {
|
||||||
@@ -259,6 +264,10 @@ class ToastManager {
|
|||||||
message = success.markStarAction == MarkStarAction.markStar
|
message = success.markStarAction == MarkStarAction.markStar
|
||||||
? appLocalizations.mailHasBeenStarred
|
? appLocalizations.mailHasBeenStarred
|
||||||
: appLocalizations.mailHasBeenUnstarred;
|
: appLocalizations.mailHasBeenUnstarred;
|
||||||
|
} else if (success is CreateNewLabelSuccess) {
|
||||||
|
message = appLocalizations.createLabelSuccessfullyMessage(
|
||||||
|
success.newLabel.safeDisplayName,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
log('ToastManager::showMessageSuccess: Message: $message');
|
log('ToastManager::showMessageSuccess: Message: $message');
|
||||||
if (message?.trim().isNotEmpty == true) {
|
if (message?.trim().isNotEmpty == true) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
|||||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||||
|
import 'package:labels/model/label.dart';
|
||||||
import 'package:mockito/annotations.dart';
|
import 'package:mockito/annotations.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mockito/mockito.dart';
|
||||||
import 'package:model/email/attachment.dart';
|
import 'package:model/email/attachment.dart';
|
||||||
import 'package:model/email/email_action_type.dart';
|
import 'package:model/email/email_action_type.dart';
|
||||||
import 'package:model/extensions/session_extension.dart';
|
import 'package:model/extensions/session_extension.dart';
|
||||||
|
import 'package:model/mailbox/expand_mode.dart';
|
||||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||||
import 'package:rich_text_composer/rich_text_composer.dart';
|
import 'package:rich_text_composer/rich_text_composer.dart';
|
||||||
import 'package:tmail_ui_user/features/base/before_reconnect_manager.dart';
|
import 'package:tmail_ui_user/features/base/before_reconnect_manager.dart';
|
||||||
@@ -46,6 +48,7 @@ import 'package:tmail_ui_user/features/email/domain/usecases/print_email_interac
|
|||||||
import 'package:tmail_ui_user/features/email/domain/usecases/save_template_email_interactor.dart';
|
import 'package:tmail_ui_user/features/email/domain/usecases/save_template_email_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/usecases/transform_html_email_content_interactor.dart';
|
import 'package:tmail_ui_user/features/email/domain/usecases/transform_html_email_content_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
||||||
|
import 'package:tmail_ui_user/features/labels/presentation/label_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart';
|
import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart';
|
||||||
import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart';
|
import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
|
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
|
||||||
@@ -96,6 +99,17 @@ class MockRichTextWebController extends Mock implements RichTextWebController {
|
|||||||
bool get codeViewEnabled => false;
|
bool get codeViewEnabled => false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MockLabelController extends Mock implements LabelController {
|
||||||
|
@override
|
||||||
|
RxList<Label> get labels => RxList([]);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Rx<ExpandMode> get labelListExpandMode => Rx(ExpandMode.EXPAND);
|
||||||
|
|
||||||
|
@override
|
||||||
|
RxBool get isCreateNewLabelModalVisible => RxBool(false);
|
||||||
|
}
|
||||||
|
|
||||||
class MockMailboxDashBoardController extends Mock implements MailboxDashBoardController {
|
class MockMailboxDashBoardController extends Mock implements MailboxDashBoardController {
|
||||||
@override
|
@override
|
||||||
InternalFinalCallback<void> get onStart => mockControllerCallback();
|
InternalFinalCallback<void> get onStart => mockControllerCallback();
|
||||||
@@ -151,6 +165,9 @@ class MockMailboxDashBoardController extends Mock implements MailboxDashBoardCon
|
|||||||
bool isAIScribeEndpointAvailable({Session? session, AccountId? accountId}) {
|
bool isAIScribeEndpointAvailable({Session? session, AccountId? accountId}) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
LabelController get labelController => MockLabelController();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateNiceMocks([
|
@GenerateNiceMocks([
|
||||||
|
|||||||
Reference in New Issue
Block a user