ContactDetailViewModel.swift 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import UIKit
  2. import DcCore
  3. class ContactDetailViewModel {
  4. let context: DcContext
  5. enum ProfileSections {
  6. case chatOptions
  7. case statusArea
  8. case sharedChats
  9. case chatActions
  10. }
  11. enum ChatOption {
  12. case gallery
  13. case documents
  14. case ephemeralMessages
  15. case muteChat
  16. case startChat
  17. }
  18. enum ChatAction {
  19. case archiveChat
  20. case showEncrInfo
  21. case blockContact
  22. case deleteChat
  23. }
  24. var contactId: Int
  25. // TODO: check if that is too inefficient (each bit read from contact, results in a database-query)
  26. var contact: DcContact {
  27. return DcContact(id: contactId)
  28. }
  29. let chatId: Int
  30. var isSavedMessages: Bool
  31. var isDeviceTalk: Bool
  32. private let sharedChats: DcChatlist
  33. private var sections: [ProfileSections] = []
  34. private var chatActions: [ChatAction] = []
  35. private var chatOptions: [ChatOption] = []
  36. init(dcContext: DcContext, contactId: Int) {
  37. self.context = dcContext
  38. self.contactId = contactId
  39. self.chatId = dcContext.getChatIdByContactId(contactId: contactId)
  40. self.isSavedMessages = false
  41. self.isDeviceTalk = false
  42. if chatId != 0 {
  43. let dcChat = dcContext.getChat(chatId: chatId)
  44. isSavedMessages = dcChat.isSelfTalk
  45. isDeviceTalk = dcChat.isDeviceTalk
  46. }
  47. self.sharedChats = context.getChatlist(flags: 0, queryString: nil, queryId: contactId)
  48. sections.append(.chatOptions)
  49. let dcContact = DcContact(id: contactId)
  50. if !dcContact.status.isEmpty {
  51. sections.append(.statusArea)
  52. }
  53. if sharedChats.length > 0 && !isSavedMessages && !isDeviceTalk {
  54. sections.append(.sharedChats)
  55. }
  56. sections.append(.chatActions)
  57. if chatId != 0 {
  58. chatOptions = [.gallery, .documents]
  59. if !isDeviceTalk {
  60. chatOptions.append(.ephemeralMessages)
  61. }
  62. if !isSavedMessages {
  63. chatOptions.append(.muteChat)
  64. }
  65. if !isDeviceTalk {
  66. chatOptions.append(.startChat)
  67. }
  68. chatActions = [.archiveChat]
  69. if !isDeviceTalk && !isSavedMessages {
  70. chatActions.append(.showEncrInfo)
  71. chatActions.append(.blockContact)
  72. }
  73. chatActions.append(.deleteChat)
  74. } else {
  75. chatOptions = [.gallery, .documents, .startChat]
  76. chatActions = [.showEncrInfo, .blockContact]
  77. }
  78. }
  79. func typeFor(section: Int) -> ContactDetailViewModel.ProfileSections {
  80. return sections[section]
  81. }
  82. func chatActionFor(row: Int) -> ContactDetailViewModel.ChatAction {
  83. return chatActions[row]
  84. }
  85. func chatOptionFor(row: Int) -> ContactDetailViewModel.ChatOption {
  86. return chatOptions[row]
  87. }
  88. var chatIsArchived: Bool {
  89. return chatId != 0 && context.getChat(chatId: chatId).isArchived
  90. }
  91. var chatIsMuted: Bool {
  92. return chatId != 0 && context.getChat(chatId: chatId).isMuted
  93. }
  94. var chatIsEphemeral: Bool {
  95. return chatId != 0 && context.getChatEphemeralTimer(chatId: chatId) > 0
  96. }
  97. var galleryItemMessageIds: [Int] {
  98. return context.getChatMedia(
  99. chatId: chatId,
  100. messageType: DC_MSG_IMAGE,
  101. messageType2: DC_MSG_GIF,
  102. messageType3: DC_MSG_VIDEO
  103. )
  104. }
  105. var documentItemMessageIds: [Int] {
  106. return context.getChatMedia(
  107. chatId: chatId,
  108. messageType: DC_MSG_FILE,
  109. messageType2: DC_MSG_AUDIO,
  110. messageType3: 0
  111. )
  112. }
  113. var numberOfSections: Int {
  114. return sections.count
  115. }
  116. func numberOfRowsInSection(_ section: Int) -> Int {
  117. switch sections[section] {
  118. case .chatOptions: return chatOptions.count
  119. case .statusArea: return 1
  120. case .sharedChats: return sharedChats.length
  121. case .chatActions: return chatActions.count
  122. }
  123. }
  124. func getSharedChatIdAt(indexPath: IndexPath) -> Int {
  125. let index = indexPath.row
  126. return sharedChats.getChatId(index: index)
  127. }
  128. func update(sharedChatCell cell: ContactCell, row index: Int) {
  129. let chatId = sharedChats.getChatId(index: index)
  130. let summary = sharedChats.getSummary(index: index)
  131. let unreadMessages = context.getUnreadMessages(chatId: chatId)
  132. let cellData = ChatCellData(chatId: chatId, highlightMsgId: nil, summary: summary, unreadMessages: unreadMessages)
  133. let cellViewModel = ChatCellViewModel(dcContext: context, chatData: cellData)
  134. cell.updateCell(cellViewModel: cellViewModel)
  135. }
  136. func titleFor(section: Int) -> String? {
  137. switch sections[section] {
  138. case .chatOptions: return nil
  139. case .statusArea: return String.localized("pref_default_status_label")
  140. case .sharedChats: return String.localized("profile_shared_chats")
  141. case .chatActions: return nil
  142. }
  143. }
  144. // returns true if chat is archived after action
  145. func toggleArchiveChat() -> Bool {
  146. if chatId == 0 {
  147. safe_fatalError("there is no chatId - you are probably are calling this from ContactDetail - this should be only called from ChatDetail")
  148. return false
  149. }
  150. let isArchivedBefore = chatIsArchived
  151. if !isArchivedBefore {
  152. NotificationManager.removeNotificationsForChat(chatId: chatId)
  153. }
  154. context.archiveChat(chatId: chatId, archive: !isArchivedBefore)
  155. return chatIsArchived
  156. }
  157. }