55import java .util .ArrayList ;
66import java .util .Date ;
77import java .util .HashMap ;
8+ import java .util .HashSet ;
89import java .util .List ;
910import java .util .Locale ;
1011import java .util .Map ;
12+ import java .util .Set ;
1113import java .util .regex .Pattern ;
1214import android .annotation .SuppressLint ;
1315import android .app .Activity ;
5658import com .bumptech .glide .Glide ;
5759import com .bumptech .glide .load .engine .DiskCacheStrategy ;
5860import com .fsck .k9 .activity .compose .MessageComposeInAppNotificationFragment ;
61+ import kotlin .Unit ;
5962import net .thunderbird .core .android .account .LegacyAccountDto ;
6063import app .k9mail .legacy .di .DI ;
6164import net .thunderbird .core .android .account .Identity ;
127130import net .thunderbird .core .android .contact .ContactIntentHelper ;
128131import net .thunderbird .core .featureflag .FeatureFlagProvider ;
129132import net .thunderbird .core .featureflag .compat .FeatureFlagProviderCompat ;
133+ import net .thunderbird .core .outcome .OutcomeKt ;
130134import net .thunderbird .core .preference .GeneralSettingsManager ;
131135import net .thunderbird .core .ui .theme .manager .ThemeManager ;
136+ import net .thunderbird .feature .notification .api .command .outcome .CommandExecutionFailed ;
132137import net .thunderbird .feature .notification .api .content .NotificationFactoryCoroutineCompat ;
133138import net .thunderbird .feature .notification .api .content .SentFolderNotFoundNotification ;
139+ import net .thunderbird .feature .notification .api .dismisser .NotificationDismisser ;
140+ import net .thunderbird .feature .notification .api .dismisser .compat .NotificationDismisserCompat ;
134141import net .thunderbird .feature .notification .api .sender .NotificationSender ;
135142import net .thunderbird .feature .notification .api .sender .compat .NotificationSenderCompat ;
136143import net .thunderbird .feature .search .legacy .LocalMessageSearch ;
@@ -178,6 +185,8 @@ public class MessageCompose extends K9Activity implements OnClickListener,
178185 private static final String STATE_KEY_READ_RECEIPT = "com.fsck.k9.activity.MessageCompose.messageReadReceipt" ;
179186 private static final String STATE_KEY_CHANGES_MADE_SINCE_LAST_SAVE = "com.fsck.k9.activity.MessageCompose.changesMadeSinceLastSave" ;
180187 private static final String STATE_ALREADY_NOTIFIED_USER_OF_EMPTY_SUBJECT = "alreadyNotifiedUserOfEmptySubject" ;
188+ private static final String STATE_ACTIVE_IN_APP_NOTIFICATIONS =
189+ "com.fsck.k9.activity.MessageCompose.activeInAppNotifications" ;
181190
182191 private static final String FRAGMENT_WAITING_FOR_ATTACHMENT = "waitingForAttachment" ;
183192
@@ -216,6 +225,11 @@ public class MessageCompose extends K9Activity implements OnClickListener,
216225 private final FeatureFlagProvider featureFlagProvider = DI .get (FeatureFlagProvider .class );
217226 private final NotificationSender notificationSender = DI .get (NotificationSender .class );
218227 private final NotificationSenderCompat notificationSenderCompat = new NotificationSenderCompat (notificationSender );
228+ private final NotificationDismisser notificationDismisser = DI .get (NotificationDismisser .class );
229+ private final NotificationDismisserCompat notificationDismisserCompat =
230+ new NotificationDismisserCompat (notificationDismisser );
231+
232+ private final Set <Integer > activeInAppNotifications = new HashSet <>();
219233
220234 private QuotedMessagePresenter quotedMessagePresenter ;
221235 private MessageLoaderHelper messageLoaderHelper ;
@@ -561,16 +575,56 @@ protected void onResume() {
561575 fetchAccount (getIntent ());
562576 }
563577
578+ dismissActiveInAppNotifications ();
579+ triggerIfNeededSentFolderNotFoundInAppNotification ();
580+ }
581+
582+ private void triggerIfNeededSentFolderNotFoundInAppNotification () {
564583 if (account != null && account .getSentFolderId () == null ) {
565584 final SentFolderNotFoundNotification notification = NotificationFactoryCoroutineCompat .create (
566- continuation -> SentFolderNotFoundNotification (account .getUuid (), continuation )
585+ continuation -> SentFolderNotFoundNotification (account .getUuid (), continuation )
567586 );
568587 notificationSenderCompat .send (notification , outcome -> {
569- Log .v ("notificationSender outcome = " + outcome );
588+ OutcomeKt .handle (
589+ outcome ,
590+ success -> {
591+ activeInAppNotifications .add (success .getRawNotificationId ());
592+ return Unit .INSTANCE ;
593+ },
594+ failure -> {
595+ final Throwable throwable = failure instanceof CommandExecutionFailed <?>
596+ ? ((CommandExecutionFailed <?>) failure ).getThrowable ()
597+ : null ;
598+ Log .e (throwable , "Failed to send in-app notification. Failure = " + failure );
599+ return Unit .INSTANCE ;
600+ });
570601 });
571602 }
572603 }
573604
605+ private void dismissActiveInAppNotifications () {
606+ for (Integer notificationId : activeInAppNotifications ) {
607+ notificationDismisserCompat .dismiss (
608+ notificationId ,
609+ outcome -> {
610+ OutcomeKt .handle (
611+ outcome ,
612+ success -> {
613+ activeInAppNotifications .remove (success .getRawNotificationId ());
614+ return Unit .INSTANCE ;
615+ },
616+ failure -> {
617+ final Throwable throwable = failure instanceof CommandExecutionFailed <?>
618+ ? ((CommandExecutionFailed <?>) failure ).getThrowable ()
619+ : null ;
620+ Log .e (throwable , "Failed to dismiss in-app notification. Failure = " + failure );
621+ return Unit .INSTANCE ;
622+ }
623+ );
624+ });
625+ }
626+ }
627+
574628 @ Override
575629 public void onPause () {
576630 super .onPause ();
@@ -596,7 +650,7 @@ public void onPause() {
596650 * Quoted text,
597651 */
598652 @ Override
599- protected void onSaveInstanceState (Bundle outState ) {
653+ protected void onSaveInstanceState (@ NonNull Bundle outState ) {
600654 super .onSaveInstanceState (outState );
601655
602656 outState .putBoolean (STATE_KEY_SOURCE_MESSAGE_PROCED , relatedMessageProcessed );
@@ -610,6 +664,7 @@ protected void onSaveInstanceState(Bundle outState) {
610664 outState .putBoolean (STATE_KEY_READ_RECEIPT , requestReadReceipt );
611665 outState .putBoolean (STATE_KEY_CHANGES_MADE_SINCE_LAST_SAVE , changesMadeSinceLastSave );
612666 outState .putBoolean (STATE_ALREADY_NOTIFIED_USER_OF_EMPTY_SUBJECT , alreadyNotifiedUserOfEmptySubject );
667+ outState .putIntegerArrayList (STATE_ACTIVE_IN_APP_NOTIFICATIONS , new ArrayList <>(activeInAppNotifications ));
613668
614669 replyToPresenter .onSaveInstanceState (outState );
615670 recipientPresenter .onSaveInstanceState (outState );
@@ -649,6 +704,11 @@ protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
649704 referencedMessageIds = savedInstanceState .getString (STATE_REFERENCES );
650705 changesMadeSinceLastSave = savedInstanceState .getBoolean (STATE_KEY_CHANGES_MADE_SINCE_LAST_SAVE );
651706 alreadyNotifiedUserOfEmptySubject = savedInstanceState .getBoolean (STATE_ALREADY_NOTIFIED_USER_OF_EMPTY_SUBJECT );
707+ final List <Integer > activeInAppNotifications = savedInstanceState
708+ .getIntegerArrayList (STATE_ACTIVE_IN_APP_NOTIFICATIONS );
709+ if (activeInAppNotifications != null && !activeInAppNotifications .isEmpty ()) {
710+ this .activeInAppNotifications .addAll (activeInAppNotifications );
711+ }
652712
653713 updateFrom ();
654714
@@ -912,6 +972,9 @@ private void onAccountChosen(LegacyAccountDto account, Identity identity) {
912972 this .account = account ;
913973 }
914974
975+ dismissActiveInAppNotifications ();
976+ triggerIfNeededSentFolderNotFoundInAppNotification ();
977+
915978 // Show CC/BCC text input field when switching to an account that always wants them
916979 // displayed.
917980 // Please note that we're not hiding the fields if the user switches back to an account
0 commit comments