ConversationUtils.m 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // _____ _
  2. // |_ _| |_ _ _ ___ ___ _ __ __ _
  3. // | | | ' \| '_/ -_) -_) ' \/ _` |_
  4. // |_| |_||_|_| \___\___|_|_|_\__,_(_)
  5. //
  6. // Threema iOS Client
  7. // Copyright (c) 2017-2020 Threema GmbH
  8. //
  9. // This program is free software: you can redistribute it and/or modify
  10. // it under the terms of the GNU Affero General Public License, version 3,
  11. // as published by the Free Software Foundation.
  12. //
  13. // This program is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. // GNU Affero General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Affero General Public License
  19. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. #import "ConversationUtils.h"
  21. #import "EntityManager.h"
  22. #import "AppDelegate.h"
  23. #import "MessageSender.h"
  24. #import "NotificationManager.h"
  25. #ifdef DEBUG
  26. static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
  27. #else
  28. static const DDLogLevel ddLogLevel = DDLogLevelWarning;
  29. #endif
  30. @implementation ConversationUtils
  31. + (void)unreadConversation:(Conversation *)conversation {
  32. if (conversation == nil)
  33. return;
  34. NSNumber *unreadValue;
  35. if (conversation.unreadMessageCount.intValue > 0) {
  36. [ConversationUtils readMessagesQueue:conversation];
  37. }
  38. if (conversation.unreadMessageCount.intValue == 0) {
  39. unreadValue = @-1;
  40. } else {
  41. unreadValue = @0;
  42. }
  43. EntityManager *entityManager = [[EntityManager alloc] init];
  44. [entityManager performSyncBlockAndSafe:^{
  45. conversation.unreadMessageCount = unreadValue;
  46. }];
  47. [[NotificationManager sharedInstance] updateUnreadMessagesCount:NO];
  48. }
  49. + (void)readMessagesQueue:(Conversation *)conversation {
  50. NSMutableArray *readReceiptQueue = [NSMutableArray new];
  51. EntityManager *entityManager = [[EntityManager alloc] init];
  52. NSArray *messages = conversation.messages.allObjects;
  53. if (conversation.groupId != nil) {
  54. for (int i = 0; i < [messages count]; i++) {
  55. BaseMessage *curMessage = [messages objectAtIndex:i];
  56. if (!curMessage.isOwn.boolValue && !curMessage.read.boolValue) {
  57. [readReceiptQueue addObject:curMessage];
  58. }
  59. }
  60. [entityManager performSyncBlockAndSafe:^{
  61. for (BaseMessage *message in readReceiptQueue) {
  62. @try {
  63. message.read = [NSNumber numberWithBool:YES];
  64. message.readDate = [NSDate date];
  65. }
  66. @catch (NSException *exception) {
  67. // intended to catch NSObjectInaccessibleException, which may happen
  68. // if the message has been deleted in the meantime
  69. DDLogError(@"Exception while marking message as read: %@", exception);
  70. }
  71. }
  72. }];
  73. [readReceiptQueue removeAllObjects];
  74. return;
  75. } else {
  76. for (int i = 0; i < [messages count]; i++) {
  77. BaseMessage *curMessage = [messages objectAtIndex:i];
  78. if (!curMessage.isOwn.boolValue && !curMessage.read.boolValue) {
  79. [readReceiptQueue addObject:curMessage];
  80. }
  81. }
  82. }
  83. /* do not send read receipts while app is in the background */
  84. if (![AppDelegate sharedAppDelegate].active)
  85. return;
  86. if (readReceiptQueue.count > 0) {
  87. [MessageSender sendReadReceiptForMessages:readReceiptQueue toIdentity:conversation.contact.identity async:YES quickReply:NO];
  88. [entityManager performSyncBlockAndSafe:^{
  89. for (BaseMessage *message in readReceiptQueue) {
  90. @try {
  91. message.read = [NSNumber numberWithBool:YES];
  92. message.readDate = [NSDate date];
  93. }
  94. @catch (NSException *exception) {
  95. // intended to catch NSObjectInaccessibleException, which may happen
  96. // if the message has been deleted in the meantime
  97. DDLogError(@"Exception while marking message as read: %@", exception);
  98. }
  99. }
  100. }];
  101. [readReceiptQueue removeAllObjects];
  102. }
  103. }
  104. + (void)markConversation:(Conversation *)conversation {
  105. if (conversation == nil)
  106. return;
  107. EntityManager *entityManager = [[EntityManager alloc] init];
  108. [entityManager performSyncBlockAndSafe:^{
  109. conversation.marked = [NSNumber numberWithBool:YES];
  110. }];
  111. }
  112. + (void)unmarkConversation:(Conversation *)conversation {
  113. if (conversation == nil)
  114. return;
  115. EntityManager *entityManager = [[EntityManager alloc] init];
  116. [entityManager performSyncBlockAndSafe:^{
  117. conversation.marked = [NSNumber numberWithBool:NO];
  118. }];
  119. }
  120. /**
  121. If unread message count of conversation less 0, then set to 0 and set marked to true.
  122. */
  123. + (void)resetUnreadMessageCount {
  124. EntityManager *entityManager = [[EntityManager alloc] init];
  125. NSArray *conversations = [entityManager.entityFetcher conversationsWithNegativeUnreadMessageCount];
  126. for (Conversation *conversation in conversations) {
  127. [entityManager performSyncBlockAndSafe:^{
  128. conversation.unreadMessageCount = [NSNumber numberWithInt:0];
  129. conversation.marked = [NSNumber numberWithBool:YES];
  130. }];
  131. }
  132. }
  133. @end