diff --git a/Rocket.Chat.xcodeproj/project.pbxproj b/Rocket.Chat.xcodeproj/project.pbxproj index 0a4a63aea8..7d6b051f92 100644 --- a/Rocket.Chat.xcodeproj/project.pbxproj +++ b/Rocket.Chat.xcodeproj/project.pbxproj @@ -910,6 +910,7 @@ 99F8FAED20B66F210025FEEF /* ImageCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F8FAEC20B66F210025FEEF /* ImageCoordinator.swift */; }; A0FFC1611E8A9D8D00A1B5EA /* TintedTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0FFC1601E8A9D8D00A1B5EA /* TintedTextField.swift */; }; AB2AC99226FB9C7C9DA45E94 /* Pods_Rocket_Chat_ShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6787D07A45177F339DB234DD /* Pods_Rocket_Chat_ShareExtension.framework */; }; + B3B47AC322DCCE13006E1EF7 /* RoomDeletedMessagesRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B47AC222DCCE13006E1EF7 /* RoomDeletedMessagesRequest.swift */; }; B5893BF41F6C4A5F00365768 /* UserReviewManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5893BF31F6C4A5E00365768 /* UserReviewManager.swift */; }; B5893BF61F6C4B1D00365768 /* UserReviewManagerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5893BF51F6C4B1D00365768 /* UserReviewManagerSpec.swift */; }; D10E9C1A1F643457007F1796 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D10E9C191F643457007F1796 /* Channel.swift */; }; @@ -1899,6 +1900,7 @@ 99F8FAEC20B66F210025FEEF /* ImageCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCoordinator.swift; sourceTree = ""; }; A0FFC1601E8A9D8D00A1B5EA /* TintedTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TintedTextField.swift; sourceTree = ""; }; AAC8D92081FF042E089F3063 /* Pods-Rocket.Chat.beta.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rocket.Chat.beta.xcconfig"; path = "Pods/Target Support Files/Pods-Rocket.Chat/Pods-Rocket.Chat.beta.xcconfig"; sourceTree = ""; }; + B3B47AC222DCCE13006E1EF7 /* RoomDeletedMessagesRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomDeletedMessagesRequest.swift; sourceTree = ""; }; B5893BF31F6C4A5E00365768 /* UserReviewManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserReviewManager.swift; sourceTree = ""; }; B5893BF51F6C4B1D00365768 /* UserReviewManagerSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserReviewManagerSpec.swift; sourceTree = ""; }; BCF38696E8EC385488688390 /* Pods-Rocket.Chat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rocket.Chat.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Rocket.Chat/Pods-Rocket.Chat.debug.xcconfig"; sourceTree = ""; }; @@ -3368,6 +3370,7 @@ 80235D1C1F740AAC00A56CA5 /* Room */ = { isa = PBXGroup; children = ( + B3B47AC222DCCE13006E1EF7 /* RoomDeletedMessagesRequest.swift */, 8062E32B20A1F8100044F407 /* RoomsRequest.swift */, 89AEB7F71F7D225D00112A09 /* RoomCreateRequest.swift */, 80A63C4E1F719F9600FE5AC4 /* RoomInfoRequest.swift */, @@ -4482,6 +4485,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, "pt-BR", @@ -5341,6 +5345,7 @@ 4162E1531D651A8800AAAE49 /* UserManager.swift in Sources */, 800FCD4C1F728EC800D9A692 /* ChannelInfoCellProtocol.swift in Sources */, 800E22841F8500A200DA84F1 /* MessagesListViewController.swift in Sources */, + B3B47AC322DCCE13006E1EF7 /* RoomDeletedMessagesRequest.swift in Sources */, 33D08E2720BD5EDC008D03EF /* NotThemeableViews.swift in Sources */, 41778EB920ED4C2C007F72F9 /* SubscriptionCellCondensed.swift in Sources */, 99805D7520C191BE00741B8E /* StyledTextField.swift in Sources */, diff --git a/Rocket.Chat/API/Clients/SubscriptionsClient.swift b/Rocket.Chat/API/Clients/SubscriptionsClient.swift index bf25368899..fc2ba7b209 100644 --- a/Rocket.Chat/API/Clients/SubscriptionsClient.swift +++ b/Rocket.Chat/API/Clients/SubscriptionsClient.swift @@ -317,4 +317,37 @@ extension SubscriptionsClient { } } } + + func loadDeletedMessages(subscription: Subscription, + realm: Realm? = Realm.current, + completion: (([String]) -> Void)? = nil) { + + let sinceDate = subscription.deletedMessagesLastUpdated + let request = RoomDeletedMessagesRequest(roomId: subscription.rid, since: sinceDate) + let identifier = subscription.identifier ?? "" + api.fetch(request, completion: {response in + switch response { + case .resource(let resource): + realm?.execute({ realm in + let deletedIDs = resource.messages?.compactMap { $0 } ?? [] + + if let sub = realm.object(ofType: Subscription.self, forPrimaryKey: identifier) { + sub.deletedMessagesLastUpdated = Date() + + let toDelete = sub.messages?.filter({ message in + return deletedIDs.contains(message.identifier ?? "") + }) + + if let toDelete = toDelete { + realm.delete(toDelete) + } + completion?(deletedIDs) + } + completion?([]) + }) + case .error: + completion?([]) + } + }) + } } diff --git a/Rocket.Chat/API/Requests/Room/RoomDeletedMessagesRequest.swift b/Rocket.Chat/API/Requests/Room/RoomDeletedMessagesRequest.swift new file mode 100644 index 0000000000..6e07e27212 --- /dev/null +++ b/Rocket.Chat/API/Requests/Room/RoomDeletedMessagesRequest.swift @@ -0,0 +1,55 @@ +// +// RoomDeletedMessagesRequest.swift +// Rocket.Chat +// +// Created by Luís Machado on 29/03/2019. +// Copyright © 2019 Rocket.Chat. All rights reserved. +// + +import SwiftyJSON + +struct RoomDeletedMessagesRequest: APIRequest { + typealias APIResourceType = RoomDeletedMessagesResource + + let path = "/api/v1/chat.getDeletedMessages" + let requiredVersion = Version(0, 73, 0) + + var query: String? + let roomId: String? + let since: Date? + + init(roomId: String, since: Date) { + self.roomId = roomId + self.since = since + + let dateFormatter = ISO8601DateFormatter() + let dateString = dateFormatter.string(from: since) + + if let encodedString = dateString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) { + self.query = "roomId=\(roomId)&since=\(encodedString)" + } + } +} + +final class RoomDeletedMessagesResource: APIResource { + var messages: [String?]? { + return raw?["messages"].arrayValue.map { + if let removedMsg = $0.dictionaryObject, let msgId = removedMsg["_id"] as? String { + return msgId + } + return nil + } + } + + var count: Int? { + return raw?["count"].int + } + + var offset: Int? { + return raw?["offset"].int + } + + var total: Int? { + return raw?["total"].int + } +} diff --git a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift index 2c45cec6a5..a3a746d4b2 100644 --- a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift +++ b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift @@ -743,6 +743,8 @@ extension MessagesViewController: SocketConnectionHandler { if state == .connected { viewModel.requestingData = .none + viewModel.fetchDeletedMessages() + if viewModel.threadIdentifier != nil { viewModel.fetchThreadMessages(from: nil) } else { diff --git a/Rocket.Chat/Controllers/Chat/MessagesViewModel.swift b/Rocket.Chat/Controllers/Chat/MessagesViewModel.swift index aa1eee1b58..f5394ca485 100644 --- a/Rocket.Chat/Controllers/Chat/MessagesViewModel.swift +++ b/Rocket.Chat/Controllers/Chat/MessagesViewModel.swift @@ -89,6 +89,7 @@ final class MessagesViewModel { }) fetchMessages(from: nil) + fetchDeletedMessages() } } @@ -648,6 +649,16 @@ final class MessagesViewModel { } } + func fetchDeletedMessages() { + guard let subscription = self.subscription, + let client = API.current()?.client(SubscriptionsClient.self) else { + return + } + client.loadDeletedMessages(subscription: subscription) { _ in + self.updateData() + } + } + // MARK: Data Manipulation /** diff --git a/Rocket.Chat/Models/Subscription/Subscription.swift b/Rocket.Chat/Models/Subscription/Subscription.swift index 2aad8f4ac3..37bc913deb 100644 --- a/Rocket.Chat/Models/Subscription/Subscription.swift +++ b/Rocket.Chat/Models/Subscription/Subscription.swift @@ -117,6 +117,11 @@ final class Subscription: BaseModel { let usersRoles = List() // MARK: Internal + + //Indicates when deleted messages were last updated. + // On new subscription objects our messages are up to date. + @objc dynamic var deletedMessagesLastUpdated: Date = Date() + @objc dynamic var privateOtherUserStatus: String? var otherUserStatus: UserStatus? { if let privateOtherUserStatus = privateOtherUserStatus {