Skip to content

Commit

Permalink
Merge pull request #2299 from bitmark-inc/3002-daily-notification
Browse files Browse the repository at this point in the history
support daily notification
  • Loading branch information
phuocbitmark authored Nov 8, 2024
2 parents 4d03afc + 84fe4fc commit 9d6ffd1
Show file tree
Hide file tree
Showing 34 changed files with 603 additions and 293 deletions.
2 changes: 1 addition & 1 deletion assets
8 changes: 4 additions & 4 deletions lib/common/injector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ import 'package:autonomy_flutter/service/metric_client_service.dart';
import 'package:autonomy_flutter/service/navigation_service.dart';
import 'package:autonomy_flutter/service/network_issue_manager.dart';
import 'package:autonomy_flutter/service/network_service.dart';
import 'package:autonomy_flutter/service/notification_service.dart';
import 'package:autonomy_flutter/service/passkey_service.dart';
import 'package:autonomy_flutter/service/pending_token_service.dart';
import 'package:autonomy_flutter/service/playlist_service.dart';
Expand All @@ -78,6 +77,7 @@ import 'package:autonomy_flutter/service/remote_config_service.dart';
import 'package:autonomy_flutter/service/settings_data_service.dart';
import 'package:autonomy_flutter/service/tezos_beacon_service.dart';
import 'package:autonomy_flutter/service/tezos_service.dart';
import 'package:autonomy_flutter/service/user_interactivity_service.dart';
import 'package:autonomy_flutter/service/versions_service.dart';
import 'package:autonomy_flutter/service/wc2_service.dart';
import 'package:autonomy_flutter/util/au_file_service.dart';
Expand Down Expand Up @@ -222,6 +222,9 @@ Future<void> setupInjector() async {
injector.registerLazySingleton(
() => UserApi(dio, baseUrl: Environment.autonomyAuthURL));

injector.registerLazySingleton<UserInteractivityService>(
() => UserInteractivityServiceImpl(injector(), injector()));

final tzktUrl = Environment.appTestnetConfig
? Environment.tzktTestnetURL
: Environment.tzktMainnetURL;
Expand Down Expand Up @@ -371,9 +374,6 @@ Future<void> setupInjector() async {
injector(),
));

injector
.registerLazySingleton<NotificationService>(() => NotificationService());

injector.registerLazySingleton<FeralFileService>(() => FeralFileServiceImpl(
injector(),
injector(),
Expand Down
2 changes: 1 addition & 1 deletion lib/gateway/iap_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ abstract class IAPApi {
Future<OnesignalIdentityHash> generateIdentityHash(
@Body() Map<String, String> body);

@GET('/apis/v2/announcements')
@GET('/apis/v2/notifications')
Future<List<Announcement>> getAnnouncements(@Body() AnnouncementRequest body);

@POST('/apis/v2/gift-code/{id}/redeem')
Expand Down
2 changes: 1 addition & 1 deletion lib/gateway/iap_api.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 43 additions & 13 deletions lib/model/additional_data/additional_data.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import 'dart:async';

import 'package:autonomy_flutter/model/additional_data/cs_view_thread.dart';
import 'package:autonomy_flutter/model/additional_data/daily_notification_data.dart';
import 'package:autonomy_flutter/model/additional_data/jg_crystalline_work_generated.dart';
import 'package:autonomy_flutter/model/additional_data/navigate_additional_data.dart';
import 'package:autonomy_flutter/model/additional_data/view_collection.dart'
Expand All @@ -14,23 +17,28 @@ import 'package:flutter/cupertino.dart';
class AdditionalData {
final NotificationType notificationType;
final String? announcementContentId;
final String? linkText;

AdditionalData({
required this.notificationType,
this.announcementContentId,
this.linkText,
});

bool get isTappable => false;

static AdditionalData fromJson(Map<String, dynamic> json, {String? type}) {
final announcementContentId = json['announcementContentID'];
final notificationContentId = json['notification_content_id'];
try {
final notificationType =
NotificationType.fromString(type ?? json['notification_type']);
final String? linkText = json['link_text'];

final defaultAdditionalData = AdditionalData(
notificationType: notificationType,
announcementContentId: announcementContentId);
notificationType: notificationType,
announcementContentId: notificationContentId,
linkText: linkText,
);

switch (notificationType) {
case NotificationType.customerSupportNewMessage:
Expand All @@ -43,14 +51,16 @@ class AdditionalData {
return CsViewThread(
issueId: issueId.toString(),
notificationType: notificationType,
announcementContentId: announcementContentId,
announcementContentId: notificationContentId,
linkText: linkText,
);
case NotificationType.artworkCreated:
case NotificationType.artworkReceived:
case NotificationType.galleryNewNft:
return view_collection_handler.ViewCollection(
notificationType: notificationType,
announcementContentId: announcementContentId,
announcementContentId: notificationContentId,
linkText: linkText,
);
case NotificationType.newMessage:
final groupId = json['group_id'];
Expand All @@ -61,7 +71,8 @@ class AdditionalData {
return ViewNewMessage(
groupId: groupId,
notificationType: notificationType,
announcementContentId: announcementContentId,
announcementContentId: notificationContentId,
linkText: linkText,
);
case NotificationType.newPostcardTrip:
case NotificationType.postcardShareExpired:
Expand All @@ -73,14 +84,16 @@ class AdditionalData {
return ViewPostcard(
indexID: indexID,
notificationType: notificationType,
announcementContentId: announcementContentId,
announcementContentId: notificationContentId,
linkText: linkText,
);
case NotificationType.jgCrystallineWorkHasArrived:
final jgExhibitionId = JohnGerrardHelper.exhibitionID;
return ViewExhibitionData(
exhibitionId: jgExhibitionId ?? '',
notificationType: notificationType,
announcementContentId: announcementContentId,
announcementContentId: notificationContentId,
linkText: linkText,
);
case NotificationType.jgCrystallineWorkGenerated:
final tokenId = json['token_id'];
Expand All @@ -91,7 +104,8 @@ class AdditionalData {
return JgCrystallineWorkGenerated(
tokenId: tokenId,
notificationType: notificationType,
announcementContentId: announcementContentId,
announcementContentId: notificationContentId,
linkText: linkText,
);
case NotificationType.exhibitionViewingOpening:
case NotificationType.exhibitionSalesOpening:
Expand All @@ -104,31 +118,47 @@ class AdditionalData {
return ViewExhibitionData(
exhibitionId: exhibitionId,
notificationType: notificationType,
announcementContentId: announcementContentId,
announcementContentId: notificationContentId,
linkText: linkText,
);
case NotificationType.navigate:
final navigationRoute = json['navigation_route'];
final homeIndex = json['home_index'];
return NavigateAdditionalData(
navigationRoute: navigationRoute,
notificationType: notificationType,
announcementContentId: announcementContentId,
announcementContentId: notificationContentId,
homeIndex: homeIndex,
linkText: linkText,
);
case NotificationType.dailyArtworkReminders:
final subType = json['notification_sub_type'];
final dailyType = DailyNotificationType.fromString(subType ?? '');
if (dailyType == null) {
log.warning('AdditionalData: dailyType is null');
return defaultAdditionalData;
}
return DailyNotificationData(
dailyNotificationType: dailyType,
notificationType: notificationType,
announcementContentId: notificationContentId,
linkText: linkText,
);

default:
return defaultAdditionalData;
}
} catch (_) {
log.info('AdditionalData: error parsing additional data');
return AdditionalData(
notificationType: NotificationType.general,
announcementContentId: announcementContentId);
announcementContentId: notificationContentId);
}
}

Future<void> handleTap(BuildContext context) async {
log.info('AdditionalData: handle tap: $notificationType');
}

bool prepareAndDidSuccess() => true;
FutureOr<bool> prepareAndDidSuccess() => true;
}
1 change: 1 addition & 0 deletions lib/model/additional_data/cs_view_thread.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class CsViewThread extends AdditionalData {
required this.issueId,
required super.notificationType,
super.announcementContentId,
super.linkText,
});

final CustomerSupportService _customerSupportService =
Expand Down
152 changes: 152 additions & 0 deletions lib/model/additional_data/daily_notification_data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import 'dart:async';

import 'package:autonomy_flutter/common/injector.dart';
import 'package:autonomy_flutter/model/additional_data/additional_data.dart';
import 'package:autonomy_flutter/model/dailies.dart';
import 'package:autonomy_flutter/screen/app_router.dart';
import 'package:autonomy_flutter/screen/dailies_work/dailies_work_bloc.dart';
import 'package:autonomy_flutter/screen/exhibition_details/exhibition_detail_page.dart';
import 'package:autonomy_flutter/screen/feralfile_series/feralfile_series_page.dart';
import 'package:autonomy_flutter/service/feralfile_service.dart';
import 'package:autonomy_flutter/service/navigation_service.dart';
import 'package:autonomy_flutter/util/log.dart';
import 'package:flutter/material.dart';
import 'package:sentry_flutter/sentry_flutter.dart';

enum DailyNotificationType {
viewDaily,
revisitDaily,
viewDailySeries,
viewDailyExhibition,
meetDailyArtist,
displayDailyOnTV,
;

static DailyNotificationType? fromString(String value) {
switch (value) {
case 'view_daily':
return DailyNotificationType.viewDaily;
case 'revisit_daily':
return DailyNotificationType.revisitDaily;
case 'view_daily_series':
return DailyNotificationType.viewDailySeries;
case 'view_daily_exhibition':
return DailyNotificationType.viewDailyExhibition;
case 'meet_daily_artist':
return DailyNotificationType.meetDailyArtist;
case 'display_daily_on_tv':
return DailyNotificationType.displayDailyOnTV;
default:
log.info('DailyNotificationType: fromString: unknown value: $value');
return null;
}
}
}

class DailyNotificationData extends AdditionalData {
final DailyNotificationType dailyNotificationType;

final _navigationService = injector<NavigationService>();
final _feralFileService = injector<FeralFileService>();
final _dailyWorkBloc = injector<DailyWorkBloc>();

DailyNotificationData({
required this.dailyNotificationType,
required super.notificationType,
super.announcementContentId,
super.linkText,
});

@override
bool get isTappable => true;

@override
Future<void> handleTap(BuildContext context) async {
log.info('DailyNotificationData: handle tap');
bool isDailyTokenAvailable = await prepareAndDidSuccess();
if (!isDailyTokenAvailable) {
_logAndSendSentryForNullData('dailyToken');
return;
}
final dailyToken = _dailyWorkBloc.state.currentDailyToken;
switch (dailyNotificationType) {
case DailyNotificationType.viewDaily:
case DailyNotificationType.revisitDaily:
await _navigationService.navigatePath(AppRouter.dailyWorkPage);
case DailyNotificationType.viewDailySeries:
final artwork = dailyToken!.artwork;
if (artwork == null) {
_logAndSendSentryForNullData('artwork');
return;
}
final series = await _feralFileService.getSeries(artwork.seriesID);
if (!context.mounted) {
return;
}
await Navigator.of(context).pushNamed(
AppRouter.feralFileSeriesPage,
arguments: FeralFileSeriesPagePayload(
seriesId: artwork.seriesID,
exhibitionId: series.exhibitionID,
),
);
case DailyNotificationType.viewDailyExhibition:
final artwork = dailyToken!.artwork;
if (artwork == null) {
_logAndSendSentryForNullData('artwork');
return;
}
final series = await _feralFileService.getSeries(artwork.seriesID);
final exhibition = series.exhibition;
if (exhibition == null) {
_logAndSendSentryForNullData('exhibition');
return;
}
if (!context.mounted) {
return;
}
await Navigator.of(context).pushNamed(
AppRouter.exhibitionDetailPage,
arguments:
ExhibitionDetailPayload(exhibitions: [exhibition], index: 0),
);
case DailyNotificationType.meetDailyArtist:
final artistID = _dailyWorkBloc.state.assetTokens.firstOrNull?.artistID;

if (artistID == null) {
_logAndSendSentryForNullData('artistID');
return;
}
await injector<NavigationService>().openFeralFileArtistPage(artistID);
case DailyNotificationType.displayDailyOnTV:
await _navigationService.navigatePath(AppRouter.dailyWorkPage);
await Future.delayed(const Duration(milliseconds: 300), () {
dailyWorkKey.currentState?.openDisplayDialog();
});

default:
}
}

void _logAndSendSentryForNullData(String data) {
log.warning('DailyNotificationData: $data is null');
unawaited(Sentry.captureMessage('DailyNotificationData: $data is null'));
}

@override
Future<bool> prepareAndDidSuccess() async {
DailyToken? dailyToken = _dailyWorkBloc.state.currentDailyToken;
if (dailyToken == null) {
log.warning('DailyNotificationData: dailyToken is null, retrying');
await Future.delayed(const Duration(milliseconds: 1000));
dailyToken = _dailyWorkBloc.state.currentDailyToken;
}
if (dailyToken == null) {
log.warning('DailyNotificationData: dailyToken is null');
unawaited(
Sentry.captureMessage('DailyNotificationData: dailyToken is null'));
return false;
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class JgCrystallineWorkGenerated extends AdditionalData {
required this.tokenId,
required super.notificationType,
super.announcementContentId,
super.linkText,
});

@override
Expand Down
1 change: 1 addition & 0 deletions lib/model/additional_data/navigate_additional_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class NavigateAdditionalData extends AdditionalData {
required this.navigationRoute,
required super.notificationType,
super.announcementContentId,
super.linkText,
this.homeIndex,
});

Expand Down
1 change: 1 addition & 0 deletions lib/model/additional_data/view_collection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class ViewCollection extends AdditionalData {
ViewCollection({
required super.notificationType,
super.announcementContentId,
super.linkText,
});

@override
Expand Down
1 change: 1 addition & 0 deletions lib/model/additional_data/view_exhibition.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class ViewExhibitionData extends AdditionalData {
required this.exhibitionId,
required super.notificationType,
super.announcementContentId,
super.linkText,
});

@override
Expand Down
Loading

0 comments on commit 9d6ffd1

Please sign in to comment.