diff --git a/Riot/Categories/MXRoomSummary.swift b/Riot/Categories/MXRoomSummary.swift new file mode 100644 index 000000000..691f534d0 --- /dev/null +++ b/Riot/Categories/MXRoomSummary.swift @@ -0,0 +1,57 @@ +// +// Copyright 2024 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +extension Notification.Name { + static let roomSummaryDidRemoveExpiredDataFromStore = Notification.Name(MXRoomSummary.roomSummaryDidRemoveExpiredDataFromStore) +} + +@objc extension MXRoomSummary { + static let roomSummaryDidRemoveExpiredDataFromStore = "roomSummaryDidRemoveExpiredDataFromStore" + + private enum Constants { + static let roomRetentionInDaysKey = "roomRetentionInDays" + } + /// Get the room messages retention period in days + func roomRetentionPeriodInDays() -> uint { + if let period = self.others[Constants.roomRetentionInDaysKey] as? uint { + return period + } else { + return 365 + } + } + + /// Get the timestamp below which the received messages must be removed from the store, and the display + func mininumTimestamp() -> UInt64 { + let periodInMs = Tools.durationInMs(fromDays: self.roomRetentionPeriodInDays()) + let currentTs = (UInt64)(Date().timeIntervalSince1970 * 1000) + return (currentTs - periodInMs) + } + + /// Remove the expired messages from the store. + /// If some data are removed, this operation posts the notification: roomSummaryDidRemoveExpiredDataFromStore. + /// This operation does not commit the potential change. We let the caller trigger the commit when this is the more suitable. + /// + /// Provide a boolean telling whether some data have been removed. + func removeExpiredRoomContentsFromStore() -> Bool { + let ret = self.mxSession.store.removeAllMessagesSent(before: self.mininumTimestamp(), inRoom: roomId) + if ret { + NotificationCenter.default.post(name: .roomSummaryDidRemoveExpiredDataFromStore, object: self) + } + return ret + } +} diff --git a/Riot/Categories/MXSession.swift b/Riot/Categories/MXSession.swift index 10df98141..5300c1ec3 100644 --- a/Riot/Categories/MXSession.swift +++ b/Riot/Categories/MXSession.swift @@ -26,3 +26,18 @@ extension MXSession { displayName: user?.displayname) } } + +@objc extension MXSession { + + /// Clean the storage of a session by removing the expired contents. + func removeExpiredMessages() { + var hasStoreChanged = false + for room in self.rooms { + hasStoreChanged = hasStoreChanged || room.summary.removeExpiredRoomContentsFromStore() + } + + if hasStoreChanged { + self.store.commit?() + } + } +} diff --git a/Riot/Utils/Tools.h b/Riot/Utils/Tools.h index 57eacbcdb..8d54e06b1 100644 --- a/Riot/Utils/Tools.h +++ b/Riot/Utils/Tools.h @@ -48,4 +48,17 @@ */ + (NSURL*)fixURLWithSeveralHashKeys:(NSURL*)url; +#pragma mark - Time utilities + +/** + * Convert a number of days to a duration in ms. + */ ++ (uint64_t)durationInMsFromDays:(uint)days; + +/** + * Convert a duration in ms to a number of days. + */ ++ (uint)numberOfDaysFromDurationInMs:(uint64_t)duration; + + @end diff --git a/Riot/Utils/Tools.m b/Riot/Utils/Tools.m index 128fe3694..5866273ac 100644 --- a/Riot/Utils/Tools.m +++ b/Riot/Utils/Tools.m @@ -117,4 +117,16 @@ return fixedURL; } +#pragma mark - Time utilities + ++ (uint64_t)durationInMsFromDays:(uint)days +{ + return days * (uint64_t)(86400000); +} + ++ (uint)numberOfDaysFromDurationInMs:(uint64_t)duration +{ + return (uint)(duration / 86400000); +} + @end