TF-4233 Implement edit label action
This commit is contained in:
@@ -17,4 +17,11 @@ extension ListLabelExtension on List<Label> {
|
||||
|
||||
List<KeyWordIdentifier> get keywords =>
|
||||
map((label) => label.keyword).nonNulls.toList();
|
||||
|
||||
List<String> getDisplayNameListWithoutSelectedLabel(Label selectedLabel) {
|
||||
return map((label) => label.safeDisplayName)
|
||||
.where((name) =>
|
||||
name.trim().isNotEmpty && name != selectedLabel.safeDisplayName)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:labels/model/label.dart';
|
||||
import 'package:tmail_ui_user/features/labels/domain/model/edit_label_request.dart';
|
||||
|
||||
abstract class LabelDatasource {
|
||||
Future<List<Label>> getAllLabels(AccountId accountId);
|
||||
|
||||
Future<Label> createNewLabel(AccountId accountId, Label labelData);
|
||||
|
||||
Future<Label> editLabel(AccountId accountId, EditLabelRequest labelRequest);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:labels/model/label.dart';
|
||||
import 'package:tmail_ui_user/features/labels/data/datasource/label_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/labels/data/network/label_api.dart';
|
||||
import 'package:tmail_ui_user/features/labels/domain/model/edit_label_request.dart';
|
||||
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
|
||||
|
||||
class LabelDatasourceImpl extends LabelDatasource {
|
||||
@@ -23,4 +24,11 @@ class LabelDatasourceImpl extends LabelDatasource {
|
||||
return await _labelApi.createNewLabel(accountId, labelData);
|
||||
}).catchError(_exceptionThrower.throwException);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Label> editLabel(AccountId accountId, EditLabelRequest labelRequest) {
|
||||
return Future.sync(() async {
|
||||
return await _labelApi.editLabel(accountId, labelRequest);
|
||||
}).catchError(_exceptionThrower.throwException);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import 'package:jmap_dart_client/http/http_client.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/patch_object.dart';
|
||||
import 'package:jmap_dart_client/jmap/jmap_request.dart';
|
||||
import 'package:labels/labels.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/handle_error_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/labels/domain/model/edit_label_request.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class LabelApi with HandleSetErrorMixin {
|
||||
@@ -57,4 +59,40 @@ class LabelApi with HandleSetErrorMixin {
|
||||
throw parseErrorForSetResponse(response, generateCreateId);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Label> editLabel(
|
||||
AccountId accountId,
|
||||
EditLabelRequest labelRequest,
|
||||
) async {
|
||||
final labelId = labelRequest.labelId;
|
||||
final newLabel = labelRequest.newLabel;
|
||||
|
||||
final method = SetLabelMethod(accountId)
|
||||
..addUpdates({
|
||||
labelId: PatchObject(newLabel.toJson())
|
||||
});
|
||||
|
||||
final builder = JmapRequestBuilder(_httpClient, ProcessingInvocation());
|
||||
final invocation = builder.invocation(method);
|
||||
|
||||
final result =
|
||||
await (builder..usings(method.requiredCapabilities)).build().execute();
|
||||
|
||||
final response = result.parse<SetLabelResponse>(
|
||||
invocation.methodCallId,
|
||||
SetLabelResponse.deserialize,
|
||||
);
|
||||
|
||||
final labelUpdated = response?.updated?[labelId];
|
||||
|
||||
if (labelUpdated != null) {
|
||||
final newLabelUpdated = newLabel.copyWith(
|
||||
id: labelId,
|
||||
keyword: labelRequest.labelKeyword,
|
||||
);
|
||||
return newLabelUpdated;
|
||||
} else {
|
||||
throw parseErrorForSetResponse(response, labelId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:labels/model/label.dart';
|
||||
import 'package:tmail_ui_user/features/labels/data/datasource/label_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/labels/domain/model/edit_label_request.dart';
|
||||
import 'package:tmail_ui_user/features/labels/domain/repository/label_repository.dart';
|
||||
|
||||
class LabelRepositoryImpl extends LabelRepository {
|
||||
@@ -17,4 +18,9 @@ class LabelRepositoryImpl extends LabelRepository {
|
||||
Future<Label> createNewLabel(AccountId accountId, Label labelData) {
|
||||
return _labelDatasource.createNewLabel(accountId, labelData);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Label> editLabel(AccountId accountId, EditLabelRequest labelRequest) {
|
||||
return _labelDatasource.editLabel(accountId, labelRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
|
||||
import 'package:labels/model/label.dart';
|
||||
|
||||
class EditLabelRequest with EquatableMixin {
|
||||
final Id labelId;
|
||||
final KeyWordIdentifier? labelKeyword;
|
||||
final Label newLabel;
|
||||
|
||||
EditLabelRequest({
|
||||
required this.labelId,
|
||||
required this.labelKeyword,
|
||||
required this.newLabel,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [labelId, labelKeyword, newLabel];
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:labels/model/label.dart';
|
||||
import 'package:tmail_ui_user/features/labels/domain/model/edit_label_request.dart';
|
||||
|
||||
abstract class LabelRepository {
|
||||
Future<List<Label>> getAllLabels(AccountId accountId);
|
||||
|
||||
Future<Label> createNewLabel(AccountId accountId, Label labelData);
|
||||
|
||||
Future<Label> editLabel(AccountId accountId, EditLabelRequest labelRequest);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:labels/model/label.dart';
|
||||
|
||||
class EditingLabel extends LoadingState {}
|
||||
|
||||
class EditLabelSuccess extends UIState {
|
||||
final Label newLabel;
|
||||
|
||||
EditLabelSuccess(this.newLabel);
|
||||
|
||||
@override
|
||||
List<Object> get props => [newLabel];
|
||||
}
|
||||
|
||||
class EditLabelFailure extends FeatureFailure {
|
||||
EditLabelFailure(dynamic exception) : super(exception: exception);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
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/labels/domain/model/edit_label_request.dart';
|
||||
import 'package:tmail_ui_user/features/labels/domain/repository/label_repository.dart';
|
||||
import 'package:tmail_ui_user/features/labels/domain/state/edit_label_state.dart';
|
||||
|
||||
class EditLabelInteractor {
|
||||
final LabelRepository _labelRepository;
|
||||
|
||||
EditLabelInteractor(this._labelRepository);
|
||||
|
||||
Stream<Either<Failure, Success>> execute(
|
||||
AccountId accountId,
|
||||
EditLabelRequest labelRequest,
|
||||
) async* {
|
||||
try {
|
||||
yield Right(EditingLabel());
|
||||
final newLabel = await _labelRepository.editLabel(
|
||||
accountId,
|
||||
labelRequest,
|
||||
);
|
||||
yield Right(EditLabelSuccess(newLabel));
|
||||
} catch (e) {
|
||||
yield Left(EditLabelFailure(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,16 @@
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:labels/extensions/list_label_extension.dart';
|
||||
import 'package:labels/model/label.dart';
|
||||
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/labels/domain/model/edit_label_request.dart';
|
||||
import 'package:tmail_ui_user/features/labels/domain/state/edit_label_state.dart';
|
||||
import 'package:tmail_ui_user/features/labels/presentation/label_controller.dart';
|
||||
import 'package:tmail_ui_user/features/labels/presentation/models/label_action_type.dart';
|
||||
import 'package:tmail_ui_user/features/labels/presentation/widgets/create_new_label_modal.dart';
|
||||
import 'package:tmail_ui_user/main/exceptions/logic_exception.dart';
|
||||
import 'package:tmail_ui_user/main/routes/dialog_router.dart';
|
||||
|
||||
extension HandleLabelActionTypeExtension on LabelController {
|
||||
void handleLabelActionType({
|
||||
@@ -14,7 +23,69 @@ extension HandleLabelActionTypeExtension on LabelController {
|
||||
openCreateNewLabelModal(accountId);
|
||||
break;
|
||||
case LabelActionType.edit:
|
||||
if (label == null) return;
|
||||
openEditLabelModal(accountId: accountId, label: label);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> openEditLabelModal({
|
||||
required AccountId? accountId,
|
||||
required Label label,
|
||||
}) async {
|
||||
await DialogRouter().openDialogModal(
|
||||
child: CreateNewLabelModal(
|
||||
labels: labels,
|
||||
selectedLabel: label,
|
||||
actionType: LabelActionType.edit,
|
||||
onCreateNewLabelCallback: (newLabel) =>
|
||||
editLabel(
|
||||
accountId: accountId,
|
||||
selectedLabel: label,
|
||||
newLabel: newLabel,
|
||||
),
|
||||
),
|
||||
dialogLabel: 'edit-label-modal',
|
||||
);
|
||||
}
|
||||
|
||||
void editLabel({
|
||||
required AccountId? accountId,
|
||||
required Label selectedLabel,
|
||||
required Label newLabel,
|
||||
}) {
|
||||
log('LabelController::editLabel:selectedLabel: $selectedLabel, newLabel: $newLabel');
|
||||
if (accountId == null) {
|
||||
consumeState(
|
||||
Stream.value(Left(EditLabelFailure(NotFoundAccountIdException()))),
|
||||
);
|
||||
} else if (editLabelInteractor == null) {
|
||||
consumeState(
|
||||
Stream.value(Left(EditLabelFailure(InteractorNotInitialized()))),
|
||||
);
|
||||
} else {
|
||||
final labelRequest = EditLabelRequest(
|
||||
labelId: selectedLabel.id!,
|
||||
labelKeyword: selectedLabel.keyword,
|
||||
newLabel: newLabel,
|
||||
);
|
||||
|
||||
consumeState(editLabelInteractor!.execute(accountId, labelRequest));
|
||||
}
|
||||
}
|
||||
|
||||
void handleEditLabelSuccess(EditLabelSuccess success) {
|
||||
toastManager.showMessageSuccess(success);
|
||||
syncListLabels(success.newLabel);
|
||||
}
|
||||
|
||||
void handleEditLabelFailure(EditLabelFailure failure) {
|
||||
toastManager.showMessageFailure(failure);
|
||||
}
|
||||
|
||||
void syncListLabels(Label newLabel) {
|
||||
labels.removeWhere((label) => label.id == newLabel.id);
|
||||
labels.add(newLabel);
|
||||
labels.sortByAlphabetically();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,12 @@ import 'package:model/mailbox/expand_mode.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/edit_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/edit_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/extensions/handle_label_action_type_extension.dart';
|
||||
import 'package:tmail_ui_user/features/labels/presentation/label_interactor_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/labels/presentation/mixin/label_context_menu_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/labels/presentation/widgets/create_new_label_modal.dart';
|
||||
@@ -33,6 +36,7 @@ class LabelController extends BaseController with LabelContextMenuMixin {
|
||||
GetAllLabelInteractor? _getAllLabelInteractor;
|
||||
CreateNewLabelInteractor? _createNewLabelInteractor;
|
||||
GetLabelSettingStateInteractor? _getLabelSettingStateInteractor;
|
||||
EditLabelInteractor? _editLabelInteractor;
|
||||
|
||||
bool isLabelCapabilitySupported(Session session, AccountId accountId) {
|
||||
return LabelsConstants.labelsCapability.isSupported(session, accountId);
|
||||
@@ -57,8 +61,11 @@ class LabelController extends BaseController with LabelContextMenuMixin {
|
||||
LabelInteractorBindings().dependencies();
|
||||
_getAllLabelInteractor = getBinding<GetAllLabelInteractor>();
|
||||
_createNewLabelInteractor = getBinding<CreateNewLabelInteractor>();
|
||||
_editLabelInteractor = getBinding<EditLabelInteractor>();
|
||||
}
|
||||
|
||||
EditLabelInteractor? get editLabelInteractor => _editLabelInteractor;
|
||||
|
||||
void getAllLabels(AccountId accountId) {
|
||||
if (_getAllLabelInteractor == null) return;
|
||||
|
||||
@@ -130,6 +137,8 @@ class LabelController extends BaseController with LabelContextMenuMixin {
|
||||
_handleCreateNewLabelSuccess(success);
|
||||
} else if (success is GetLabelSettingStateSuccess) {
|
||||
_handleGetLabelSettingStateSuccess(success.isEnabled, success.accountId);
|
||||
} else if (success is EditLabelSuccess) {
|
||||
handleEditLabelSuccess(success);
|
||||
} else {
|
||||
super.handleSuccessViewState(success);
|
||||
}
|
||||
@@ -144,6 +153,8 @@ class LabelController extends BaseController with LabelContextMenuMixin {
|
||||
} else if (failure is GetLabelSettingStateFailure) {
|
||||
isLabelSettingEnabled.value = false;
|
||||
_clearLabelData();
|
||||
} else if (failure is EditLabelFailure) {
|
||||
handleEditLabelFailure(failure);
|
||||
} else {
|
||||
super.handleFailureViewState(failure);
|
||||
}
|
||||
@@ -153,6 +164,7 @@ class LabelController extends BaseController with LabelContextMenuMixin {
|
||||
void onClose() {
|
||||
_getAllLabelInteractor = null;
|
||||
_createNewLabelInteractor = null;
|
||||
_editLabelInteractor = null;
|
||||
_getLabelSettingStateInteractor = null;
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ 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/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/edit_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/main/exceptions/remote_exception_thrower.dart';
|
||||
@@ -33,6 +34,7 @@ class LabelInteractorBindings extends InteractorsBindings {
|
||||
void bindingsInteractor() {
|
||||
Get.lazyPut(() => GetAllLabelInteractor(Get.find<LabelRepository>()));
|
||||
Get.lazyPut(() => CreateNewLabelInteractor(Get.find<LabelRepository>()));
|
||||
Get.lazyPut(() => EditLabelInteractor(Get.find<LabelRepository>()));
|
||||
Get.lazyPut(() => VerifyNameInteractor());
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,29 @@ enum LabelActionType {
|
||||
switch (this) {
|
||||
case LabelActionType.create:
|
||||
return appLocalizations.createANewLabel;
|
||||
case LabelActionType.edit:
|
||||
return appLocalizations.editLabel;
|
||||
}
|
||||
}
|
||||
|
||||
String getModalSubtitle(AppLocalizations appLocalizations) {
|
||||
switch (this) {
|
||||
case LabelActionType.create:
|
||||
return appLocalizations.organizeYourInboxWithACustomCategory;
|
||||
case LabelActionType.edit:
|
||||
return appLocalizations.updateTheLabelName;
|
||||
}
|
||||
}
|
||||
|
||||
String getModalPositiveAction(AppLocalizations appLocalizations) {
|
||||
switch (this) {
|
||||
case LabelActionType.create:
|
||||
return appLocalizations.createLabel;
|
||||
case LabelActionType.edit:
|
||||
return appLocalizations.save;
|
||||
}
|
||||
}
|
||||
|
||||
String getContextMenuIcon(ImagePaths imagePaths) {
|
||||
switch (this) {
|
||||
case LabelActionType.create:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/extensions/hex_color_extension.dart';
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
@@ -13,6 +14,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:labels/labels.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/label_input_field_builder.dart';
|
||||
import 'package:tmail_ui_user/features/labels/presentation/models/label_action_type.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/name_with_space_only_validator.dart';
|
||||
@@ -27,12 +29,16 @@ typedef OnCreateNewLabelCallback = Function(Label label);
|
||||
|
||||
class CreateNewLabelModal extends StatefulWidget {
|
||||
final List<Label> labels;
|
||||
final LabelActionType actionType;
|
||||
final OnCreateNewLabelCallback onCreateNewLabelCallback;
|
||||
final Label? selectedLabel;
|
||||
|
||||
const CreateNewLabelModal({
|
||||
super.key,
|
||||
required this.labels,
|
||||
required this.onCreateNewLabelCallback,
|
||||
this.actionType = LabelActionType.create,
|
||||
this.selectedLabel,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -56,7 +62,23 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_labelDisplayNameList = widget.labels.displayNameNotNullList;
|
||||
final selectedLabel = widget.selectedLabel;
|
||||
final labels = widget.labels;
|
||||
if (selectedLabel != null) {
|
||||
_selectedColor = selectedLabel.color?.value.toColor();
|
||||
_labelDisplayNameList = labels
|
||||
.getDisplayNameListWithoutSelectedLabel(selectedLabel);
|
||||
} else {
|
||||
_labelDisplayNameList = labels.displayNameNotNullList;
|
||||
}
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (selectedLabel != null) {
|
||||
_nameInputController.text = selectedLabel.safeDisplayName;
|
||||
_nameInputFocusNode.requestFocus();
|
||||
_labelSelectedColorNotifier.value = _selectedColor;
|
||||
_createLabelStateNotifier.value = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -97,42 +119,8 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
height: 64,
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsetsDirectional.only(
|
||||
start: 32,
|
||||
end: 32,
|
||||
top: 16,
|
||||
bottom: isMobile ? 0 : 16,
|
||||
),
|
||||
child: Text(
|
||||
appLocalizations.createANewLabel,
|
||||
style: theme.textTheme.headlineSmall?.copyWith(
|
||||
color: AppColor.m3SurfaceBackground,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsetsDirectional.only(
|
||||
start: 32,
|
||||
end: 32,
|
||||
bottom: 24,
|
||||
),
|
||||
child: Text(
|
||||
appLocalizations.organizeYourInboxWithACustomCategory,
|
||||
style: ThemeUtils.textStyleInter400.copyWith(
|
||||
color: AppColor.steelGrayA540,
|
||||
fontSize: 13,
|
||||
height: 20 / 13,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
_buildTitle(appLocalizations, isMobile, theme),
|
||||
_buildSubTitle(appLocalizations),
|
||||
Flexible(
|
||||
child: SingleChildScrollView(
|
||||
physics: const ClampingScrollPhysics(),
|
||||
@@ -146,34 +134,7 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ValueListenableBuilder(
|
||||
valueListenable: _labelNameErrorTextNotifier,
|
||||
builder: (_, errorText, __) {
|
||||
return LabelInputFieldBuilder(
|
||||
label: appLocalizations.labelName,
|
||||
hintText: appLocalizations
|
||||
.pleaseEnterNameYourNewLabel,
|
||||
textEditingController: _nameInputController,
|
||||
focusNode: _nameInputFocusNode,
|
||||
errorText: errorText,
|
||||
arrangeHorizontally: false,
|
||||
isLabelHasColon: false,
|
||||
labelStyle:
|
||||
ThemeUtils.textStyleInter600().copyWith(
|
||||
fontSize: 14,
|
||||
height: 18 / 14,
|
||||
color: Colors.black,
|
||||
),
|
||||
runSpacing: 16,
|
||||
inputFieldMaxWidth: double.infinity,
|
||||
onTextChange: (value) =>
|
||||
_onLabelNameInputChanged(
|
||||
appLocalizations,
|
||||
value,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
_buildLabelNameInputField(appLocalizations),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 26, bottom: 16),
|
||||
child: Text(
|
||||
@@ -213,7 +174,7 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
||||
valueListenable: _createLabelStateNotifier,
|
||||
builder: (_, value, __) {
|
||||
return ModalListActionButtonWidget(
|
||||
positiveLabel: appLocalizations.createLabel,
|
||||
positiveLabel: widget.actionType.getModalPositiveAction(appLocalizations),
|
||||
negativeLabel: appLocalizations.cancel,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 25,
|
||||
@@ -258,6 +219,83 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildTitle(
|
||||
AppLocalizations appLocalizations,
|
||||
bool isMobile,
|
||||
ThemeData theme,
|
||||
) {
|
||||
return Container(
|
||||
height: 64,
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsetsDirectional.only(
|
||||
start: 32,
|
||||
end: 32,
|
||||
top: 16,
|
||||
bottom: isMobile ? 0 : 16,
|
||||
),
|
||||
child: Text(
|
||||
widget.actionType.getModalTitle(appLocalizations),
|
||||
style: theme.textTheme.headlineSmall?.copyWith(
|
||||
color: AppColor.m3SurfaceBackground,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSubTitle(AppLocalizations appLocalizations) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsetsDirectional.only(
|
||||
start: 32,
|
||||
end: 32,
|
||||
bottom: 24,
|
||||
),
|
||||
child: Text(
|
||||
widget.actionType.getModalSubtitle(appLocalizations),
|
||||
style: ThemeUtils.textStyleInter400.copyWith(
|
||||
color: AppColor.steelGrayA540,
|
||||
fontSize: 13,
|
||||
height: 20 / 13,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLabelNameInputField(AppLocalizations appLocalizations) {
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: _labelNameErrorTextNotifier,
|
||||
builder: (_, errorText, __) {
|
||||
return LabelInputFieldBuilder(
|
||||
label: appLocalizations.labelName,
|
||||
hintText: appLocalizations
|
||||
.pleaseEnterNameYourNewLabel,
|
||||
textEditingController: _nameInputController,
|
||||
focusNode: _nameInputFocusNode,
|
||||
errorText: errorText,
|
||||
arrangeHorizontally: false,
|
||||
isLabelHasColon: false,
|
||||
labelStyle:
|
||||
ThemeUtils.textStyleInter600().copyWith(
|
||||
fontSize: 14,
|
||||
height: 18 / 14,
|
||||
color: Colors.black,
|
||||
),
|
||||
runSpacing: 16,
|
||||
inputFieldMaxWidth: double.infinity,
|
||||
onTextChange: (value) =>
|
||||
_onLabelNameInputChanged(
|
||||
appLocalizations,
|
||||
value,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _onLabelNameInputChanged(
|
||||
AppLocalizations appLocalizations,
|
||||
String value,
|
||||
|
||||
@@ -5365,5 +5365,21 @@
|
||||
"type": "text",
|
||||
"placeholders_order": [],
|
||||
"placeholders": {}
|
||||
},
|
||||
"editLabelSuccessfullyMessage": "You successfully edited the {labelName} label",
|
||||
"@editLabelSuccessfullyMessage": {
|
||||
"type": "text",
|
||||
"placeholders_order": [
|
||||
"labelName"
|
||||
],
|
||||
"placeholders": {
|
||||
"labelName": {}
|
||||
}
|
||||
},
|
||||
"editLabelFailure": "Edit label failure",
|
||||
"@editLabelFailure": {
|
||||
"type": "text",
|
||||
"placeholders_order": [],
|
||||
"placeholders": {}
|
||||
}
|
||||
}
|
||||
@@ -5694,4 +5694,19 @@ class AppLocalizations {
|
||||
name: 'updateTheLabelName',
|
||||
);
|
||||
}
|
||||
|
||||
String editLabelSuccessfullyMessage(String labelName) {
|
||||
return Intl.message(
|
||||
'You successfully edited the $labelName label',
|
||||
name: 'editLabelSuccessfullyMessage',
|
||||
args: [labelName],
|
||||
);
|
||||
}
|
||||
|
||||
String get editLabelFailure {
|
||||
return Intl.message(
|
||||
'Edit label failure',
|
||||
name: 'editLabelFailure',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import 'package:tmail_ui_user/features/download/domain/state/preview_email_from_
|
||||
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/labels/domain/state/create_new_label_state.dart';
|
||||
import 'package:tmail_ui_user/features/labels/domain/state/edit_label_state.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/oauth_authorization_error.dart';
|
||||
@@ -209,6 +210,8 @@ class ToastManager {
|
||||
} else if (failure is AddALabelToAThreadFailure) {
|
||||
message = message ??
|
||||
appLocalizations.addLabelToThreadFailureMessage(failure.labelDisplay);
|
||||
} else if (failure is EditLabelFailure) {
|
||||
message = message ?? appLocalizations.editLabelFailure;
|
||||
}
|
||||
log('ToastManager::showMessageFailure: Message: $message');
|
||||
if (message?.trim().isNotEmpty == true) {
|
||||
@@ -276,6 +279,10 @@ class ToastManager {
|
||||
message = appLocalizations.createLabelSuccessfullyMessage(
|
||||
success.newLabel.safeDisplayName,
|
||||
);
|
||||
} else if (success is EditLabelSuccess) {
|
||||
message = appLocalizations.editLabelSuccessfullyMessage(
|
||||
success.newLabel.safeDisplayName,
|
||||
);
|
||||
} else if (success is AddALabelToAnEmailSuccess) {
|
||||
message = appLocalizations.addLabelToEmailSuccessfullyMessage(
|
||||
success.labelDisplay,
|
||||
|
||||
Reference in New Issue
Block a user