Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TF-2035 Add event action banner in email view #2053

Merged
merged 9 commits into from
Jul 26, 2023
5 changes: 5 additions & 0 deletions assets/images/ic_event_canceled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions assets/images/ic_event_invited.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions assets/images/ic_event_updated.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions core/lib/presentation/extensions/color_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,11 @@ extension AppColor on Color {
static const colorNetworkConnectionLabel = Color(0xFF818C99);
static const colorCalendarEventRead = Color(0xFF818C99);
static const colorCalendarEventUnread = Color(0xFF1C1B1F);
static const colorMaybeEventActionText = Color(0xFFFFC107);
static const colorInvitedEventActionText = Color(0xFF007AFF);
static const colorUpdatedEventActionText = Color(0xFF4BB34B);
static const colorCanceledEventActionText = Color(0xFFFF3347);
static const colorSubTitleEventActionText = Color(0xFF939393);

static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)],
Expand Down
3 changes: 3 additions & 0 deletions core/lib/presentation/resources/image_paths.dart
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ class ImagePaths {
String get icArrowRight => _getImagePath('ic_arrow_right.svg');
String get icAddPicture => _getImagePath('ic_add_picture.svg');
String get icCalendarEvent => _getImagePath('ic_calendar_event.svg');
String get icEventInvited => _getImagePath('ic_event_invited.svg');
String get icEventUpdated => _getImagePath('ic_event_updated.svg');
String get icEventCanceled => _getImagePath('ic_event_canceled.svg');

String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
Expand Down
2 changes: 1 addition & 1 deletion lib/features/base/base_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import 'package:rule_filter/rule_filter/capability_rule_filter.dart';
import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_mixin.dart';
import 'package:tmail_ui_user/features/base/mixin/popup_context_menu_action_mixin.dart';
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
import 'package:tmail_ui_user/features/email/presentation/mdn_interactor_bindings.dart';
import 'package:tmail_ui_user/features/email/presentation/bindings/mdn_interactor_bindings.dart';
import 'package:tmail_ui_user/features/login/data/network/config/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_credential_interactor.dart';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart';

abstract class CalendarEventDataSource {
Future<List<CalendarEvent>> parse(AccountId accountId, Set<Id> blobIds);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart';
import 'package:tmail_ui_user/features/email/data/datasource/calendar_event_datasource.dart';
import 'package:tmail_ui_user/features/email/data/network/calendar_event_api.dart';
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';

class CalendarEventDataSourceImpl extends CalendarEventDataSource {

final CalendarEventAPI _calendarEventAPI;
final ExceptionThrower _exceptionThrower;

CalendarEventDataSourceImpl(this._calendarEventAPI, this._exceptionThrower);

@override
Future<List<CalendarEvent>> parse(AccountId accountId, Set<Id> blobIds) {
return Future.sync(() async {
return await _calendarEventAPI.parse(accountId, blobIds);
}).catchError(_exceptionThrower.throwException);
}
}
41 changes: 41 additions & 0 deletions lib/features/email/data/network/calendar_event_api.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'dart:async';

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/jmap_request.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/parse/calendar_event_parse_method.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/parse/calendar_event_parse_response.dart';
import 'package:tmail_ui_user/features/email/domain/exceptions/calendar_event_exceptions.dart';

class CalendarEventAPI {

final HttpClient _httpClient;

CalendarEventAPI(this._httpClient);

Future<List<CalendarEvent>> parse(AccountId accountId, Set<Id> blobIds) async {
final requestBuilder = JmapRequestBuilder(_httpClient, ProcessingInvocation());
final calendarEventParseMethod = CalendarEventParseMethod(accountId, blobIds);
final calendarEventParseInvocation = requestBuilder.invocation(calendarEventParseMethod);
final response = await (requestBuilder
..usings(calendarEventParseMethod.requiredCapabilities))
.build()
.execute();

final calendarEventParseResponse = response.parse<CalendarEventParseResponse>(
calendarEventParseInvocation.methodCallId,
CalendarEventParseResponse.deserialize);

if (calendarEventParseResponse?.parsed?.isNotEmpty == true) {
return calendarEventParseResponse!.parsed!.values.toList();
} else if (calendarEventParseResponse?.notParsable?.isNotEmpty == true) {
throw NotParsableCalendarEventException();
} else if (calendarEventParseResponse?.notFound?.isNotEmpty == true) {
throw NotFoundCalendarEventException();
} else {
throw NotParsableCalendarEventException();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart';
import 'package:tmail_ui_user/features/email/data/datasource/calendar_event_datasource.dart';
import 'package:tmail_ui_user/features/email/domain/repository/calendar_event_repository.dart';

class CalendarEventRepositoryImpl extends CalendarEventRepository {

final CalendarEventDataSource _calendarEventDataSource;

CalendarEventRepositoryImpl(this._calendarEventDataSource);

@override
Future<List<CalendarEvent>> parse(AccountId accountId, Set<Id> blobIds) {
return _calendarEventDataSource.parse(accountId, blobIds);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

class NotFoundCalendarEventException implements Exception {}

class NotParsableCalendarEventException implements Exception {}
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@

import 'package:collection/collection.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:model/email/attachment.dart';
import 'package:tmail_ui_user/features/email/domain/extensions/attachment_extension.dart';
import 'package:tmail_ui_user/features/offline_mode/model/attachment_hive_cache.dart';

extension ListAttachmentsExtension on List<Attachment> {
List<AttachmentHiveCache> toHiveCache() => map((attachment) => attachment.toHiveCache()).toList();

Set<Attachment> get calendarAttachments => where((attachment) => attachment.isCalendarEvent).toSet();

Set<Id> get calendarEventBlobIds => calendarAttachments
.map((attachment) => attachment.blobId)
.whereNotNull()
.toSet();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart';

abstract class CalendarEventRepository {
Future<List<CalendarEvent>> parse(AccountId accountId, Set<Id> blobIds);
}
19 changes: 19 additions & 0 deletions lib/features/email/domain/state/parse_calendar_event_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart';

class ParseCalendarEventLoading extends LoadingState {}

class ParseCalendarEventSuccess extends UIState {

final List<CalendarEvent> calendarEventList;

ParseCalendarEventSuccess(this.calendarEventList);

@override
List<Object> get props => [calendarEventList];
}

class ParseCalendarEventFailure extends FeatureFailure {
ParseCalendarEventFailure(dynamic exception) : super(exception: exception);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
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:jmap_dart_client/jmap/core/id.dart';
import 'package:tmail_ui_user/features/email/domain/repository/calendar_event_repository.dart';
import 'package:tmail_ui_user/features/email/domain/state/parse_calendar_event_state.dart';

class ParseCalendarEventInteractor {
final CalendarEventRepository _calendarEventRepository;

ParseCalendarEventInteractor(this._calendarEventRepository);

Stream<Either<Failure, Success>> execute(AccountId accountId, Set<Id> blobIds) async* {
try {
yield Right(ParseCalendarEventLoading());
final calendarEventList = await _calendarEventRepository.parse(accountId, blobIds);
yield Right(ParseCalendarEventSuccess(calendarEventList));
} catch (e) {
yield Left(ParseCalendarEventFailure(e));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:get/get.dart';
import 'package:jmap_dart_client/http/http_client.dart';
import 'package:tmail_ui_user/features/base/interactors_bindings.dart';
import 'package:tmail_ui_user/features/email/data/datasource/calendar_event_datasource.dart';
import 'package:tmail_ui_user/features/email/data/datasource_impl/calendar_event_datasource_impl.dart';
import 'package:tmail_ui_user/features/email/data/network/calendar_event_api.dart';
import 'package:tmail_ui_user/features/email/data/repository/calendar_event_repository_impl.dart';
import 'package:tmail_ui_user/features/email/domain/repository/calendar_event_repository.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/parse_calendar_event_interactor.dart';
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';

class CalendarEventInteractorBindings extends InteractorsBindings {

@override
void bindingsDataSource() {
Get.lazyPut<CalendarEventDataSource>(() => Get.find<CalendarEventDataSourceImpl>());
}

@override
void bindingsDataSourceImpl() {
Get.lazyPut(() => CalendarEventAPI(Get.find<HttpClient>()));
Get.lazyPut(() => CalendarEventDataSourceImpl(
Get.find<CalendarEventAPI>(),
Get.find<RemoteExceptionThrower>()));
}

@override
void bindingsInteractor() {
Get.lazyPut(() => ParseCalendarEventInteractor(Get.find<CalendarEventRepository>()));
}

@override
void bindingsRepository() {
Get.lazyPut<CalendarEventRepository>(() => Get.find<CalendarEventRepositoryImpl>());
}

@override
void bindingsRepositoryImpl() {
Get.lazyPut(() => CalendarEventRepositoryImpl(Get.find<CalendarEventDataSource>()));
}
}
Loading
Loading