Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions labels/lib/extensions/label_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,23 @@ extension LabelExtension on Label {
}
}

bool get isReadOnly => readOnly == true;

Label copyWith({
Id? id,
KeyWordIdentifier? keyword,
String? displayName,
HexColor? color,
String? description,
bool? readOnly,
}) {
return Label(
id: id ?? this.id,
displayName: displayName ?? this.displayName,
keyword: keyword ?? this.keyword,
color: color ?? this.color,
description: description ?? this.description,
readOnly: readOnly ?? this.readOnly,
);
}

Expand Down
1 change: 1 addition & 0 deletions labels/lib/labels.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export 'package:labels/model/label.dart';
export 'package:labels/model/hex_color.dart';
export 'package:labels/model/labels_capability.dart';

export 'package:labels/utils/labels_constants.dart';

Expand Down
3 changes: 3 additions & 0 deletions labels/lib/model/label.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ class Label with EquatableMixin {
final String? displayName;
final HexColor? color;
final String? description;
final bool? readOnly;

Label({
this.id,
this.keyword,
this.displayName,
this.color,
this.description,
this.readOnly,
});

factory Label.fromJson(Map<String, dynamic> json) => _$LabelFromJson(json);
Expand All @@ -44,5 +46,6 @@ class Label with EquatableMixin {
displayName,
color,
description,
readOnly,
];
}
23 changes: 23 additions & 0 deletions labels/lib/model/labels_capability.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import 'package:jmap_dart_client/jmap/core/capability/capability_properties.dart';
import 'package:json_annotation/json_annotation.dart';

part 'labels_capability.g.dart';

@JsonSerializable(explicitToJson: true, includeIfNull: false)
class LabelsCapability extends CapabilityProperties {
final int? version;

LabelsCapability({this.version});

factory LabelsCapability.fromJson(Map<String, dynamic> json) =>
_$LabelsCapabilityFromJson(json);

Map<String, dynamic> toJson() => _$LabelsCapabilityToJson(this);

static LabelsCapability deserialize(Map<String, dynamic> json) {
return LabelsCapability.fromJson(json);
}

@override
List<Object?> get props => [version];
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:jmap_dart_client/jmap/core/capability/submission_capability.dart
import 'package:jmap_dart_client/jmap/core/capability/vacation_capability.dart';
import 'package:jmap_dart_client/jmap/core/capability/web_socket_ticket_capability.dart';
import 'package:jmap_dart_client/jmap/core/capability/websocket_capability.dart';
import 'package:labels/model/labels_capability.dart';
import 'package:model/saas/saas_account_capability.dart';
import 'package:model/support/contact_support_capability.dart';
import 'package:scribe/scribe/ai/presentation/model/ai_capability.dart';
Expand Down Expand Up @@ -41,6 +42,8 @@ class CapabilityPropertiesConverter {
return properties.toJson();
} else if (properties is AICapability) {
return properties.toJson();
} else if (properties is LabelsCapability) {
return properties.toJson();
} else if (properties is DefaultCapability) {
return properties.properties;
} else if (properties is EmptyCapability) {
Expand Down
21 changes: 21 additions & 0 deletions lib/features/home/domain/extensions/session_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart
import 'package:jmap_dart_client/jmap/core/capability/capability_properties.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
import 'package:labels/model/labels_capability.dart';
import 'package:labels/utils/labels_constants.dart';
import 'package:model/download_all/download_all_capability.dart';
import 'package:model/mailbox/mailbox_constants.dart';
import 'package:model/model.dart';
Expand All @@ -36,6 +38,7 @@ extension SessionExtensions on Session {
capabilityServerSettings: SettingsCapability.deserialize,
linagoraSaaSCapability: SaaSAccountCapability.deserialize,
AiScribeConstants.aiCapability: AICapability.fromJson,
LabelsConstants.labelsCapability: LabelsCapability.fromJson,
};

Map<String, dynamic> toJson() {
Expand Down Expand Up @@ -199,4 +202,22 @@ extension SessionExtensions on Session {
return null;
}
}

LabelsCapability? getLabelsCapability(AccountId accountId) {
try {
if (!LabelsConstants.labelsCapability.isSupported(this, accountId)) {
return null;
}

final labelsCapability = getCapabilityProperties<LabelsCapability>(
accountId,
LabelsConstants.labelsCapability,
);
log('SessionExtensions::getLabelsCapability:labelsCapability = $labelsCapability');
return labelsCapability;
} catch (e) {
logWarning('SessionExtensions::getLabelsCapability():[Exception] $e');
return null;
}
}
}
19 changes: 14 additions & 5 deletions lib/features/labels/presentation/label_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,18 @@ import 'package:get/get.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/state.dart';
import 'package:labels/extensions/list_label_extension.dart';
import 'package:labels/model/label.dart';
import 'package:labels/utils/labels_constants.dart';
import 'package:labels/labels.dart';
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/home/domain/extensions/session_extensions.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/delete_a_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/delete_a_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/domain/usecases/get_label_changes_interactor.dart';
import 'package:tmail_ui_user/features/labels/presentation/extensions/handle_label_action_type_extension.dart';
Expand Down Expand Up @@ -53,6 +52,7 @@ class LabelController extends BaseController with LabelContextMenuMixin {
State? _currentLabelState;
AccountId? _accountId;
Session? _session;
LabelsCapability? _labelsCapability;

@override
void onInit() {
Expand All @@ -64,9 +64,17 @@ class LabelController extends BaseController with LabelContextMenuMixin {
return LabelsConstants.labelsCapability.isSupported(session, accountId);
}

LabelsCapability? get labelsCapability => _labelsCapability;

bool get shouldAskReadOnly {
final labelVersion = labelsCapability?.version;
return labelVersion != null && labelVersion >= 1;
}

void checkLabelSettingState(Session session, AccountId accountId) {
_session = session;
_accountId = accountId;
_labelsCapability = _session?.getLabelsCapability(accountId);
_getLabelSettingStateInteractor =
getBinding<GetLabelSettingStateInteractor>();
if (_getLabelSettingStateInteractor != null) {
Expand Down Expand Up @@ -245,6 +253,7 @@ class LabelController extends BaseController with LabelContextMenuMixin {
_currentLabelState = null;
_accountId = null;
_session = null;
_labelsCapability = null;
super.onClose();
}
}
2 changes: 2 additions & 0 deletions lib/features/mailbox/presentation/base_mailbox_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
if (isLabelAvailable) {
final labelListExpandMode = labelController.labelListExpandMode.value;
final labels = labelController.labels;
final shouldAskReadOnly = labelController.shouldAskReadOnly;

return AnimatedContainer(
duration: const Duration(milliseconds: 400),
Expand All @@ -421,6 +422,7 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
labels: labels,
imagePaths: controller.imagePaths,
isDesktop: isDesktop,
shouldAskReadOnly: shouldAskReadOnly,
labelIdSelected: labelIdSelected,
isMobileResponsive: isMobileResponsive,
onOpenLabelCallback: (label) => controller.openMailbox(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class LabelListItem extends StatefulWidget {
final ImagePaths imagePaths;
final bool isDesktop;
final bool isSelected;
final bool shouldAskReadOnly;
final bool isMobileResponsive;
final OnOpenLabelCallback onOpenLabelCallback;
final OnOpenLabelContextMenuAction? onOpenContextMenu;
Expand All @@ -28,6 +29,7 @@ class LabelListItem extends StatefulWidget {
required this.onOpenLabelCallback,
this.isDesktop = false,
this.isSelected = false,
this.shouldAskReadOnly = false,
this.isMobileResponsive = false,
this.onOpenContextMenu,
this.onLongPressLabelItemAction,
Expand Down Expand Up @@ -75,7 +77,26 @@ class _LabelListItemState extends State<LabelListItem> {
: MailboxItemWidgetStyles.mobileLabelIconSpace;
}

bool get _isMenuButtonVisible => _isContextMenuVisible || _isItemHovered;
bool get _isMenuButtonVisible {
final isActive = _isContextMenuVisible || _isItemHovered;

if (!widget.shouldAskReadOnly) {
return isActive;
}

return isActive && !widget.label.isReadOnly;
}

bool get _isOnLongPressActive {
final isTouchPlatform =
PlatformInfo.isWebTouchDevice || PlatformInfo.isMobile;

if (!widget.shouldAskReadOnly) {
return isTouchPlatform;
}

return isTouchPlatform && !widget.label.isReadOnly;
}

@override
Widget build(BuildContext context) {
Expand All @@ -85,7 +106,7 @@ class _LabelListItemState extends State<LabelListItem> {
borderRadius: _borderRadius,
onHover: _handleHoverChanged,
onTap: () => widget.onOpenLabelCallback(widget.label),
onLongPress: PlatformInfo.isWebTouchDevice || PlatformInfo.isMobile
onLongPress: _isOnLongPressActive
? () => widget.onLongPressLabelItemAction?.call(widget.label)
: null,
child: Container(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class LabelListView extends StatelessWidget {
final List<Label> labels;
final ImagePaths imagePaths;
final bool isDesktop;
final bool shouldAskReadOnly;
final Id? labelIdSelected;
final OnOpenLabelCallback onOpenLabelCallback;
final bool isMobileResponsive;
Expand All @@ -21,6 +22,7 @@ class LabelListView extends StatelessWidget {
required this.imagePaths,
required this.onOpenLabelCallback,
this.isDesktop = false,
this.shouldAskReadOnly = false,
this.labelIdSelected,
this.isMobileResponsive = false,
this.onOpenContextMenu,
Expand All @@ -42,6 +44,7 @@ class LabelListView extends StatelessWidget {
imagePaths: imagePaths,
isSelected: label.id == labelIdSelected,
isDesktop: isDesktop,
shouldAskReadOnly: shouldAskReadOnly,
onOpenLabelCallback: onOpenLabelCallback,
isMobileResponsive: isMobileResponsive,
onOpenContextMenu: onOpenContextMenu,
Expand Down
Loading