WIP: disappearing messages for control messages

pull/941/head
ryanzhao 2 years ago
parent dd13125a90
commit 1c4981cb5d

@ -25,29 +25,13 @@ extension ConversationVC:
// Don't take the user to settings for unapproved threads // Don't take the user to settings for unapproved threads
guard viewModel.threadData.threadRequiresApproval == false else { return } guard viewModel.threadData.threadRequiresApproval == false else { return }
openSettings() openSettingsFromTitleView()
} }
@objc func openSettings() { @objc func openSettingsFromTitleView() {
switch self.titleView.currentLabelType { switch self.titleView.currentLabelType {
case.empty, .notificationSettings, .userCount: case.empty, .notificationSettings, .userCount:
let viewController = SessionTableViewController(viewModel: ThreadSettingsViewModel( openSettings()
threadId: self.viewModel.threadData.threadId,
threadVariant: self.viewModel.threadData.threadVariant,
didTriggerSearch: { [weak self] in
DispatchQueue.main.async {
self?.showSearchUI()
self?.popAllConversationSettingsViews {
// Note: Without this delay the search bar doesn't show
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self?.searchController.uiSearchController.searchBar.becomeFirstResponder()
}
}
}
}
)
)
navigationController?.pushViewController(viewController, animated: true)
break break
case .disappearingMessageSetting: case .disappearingMessageSetting:
let viewController = SessionTableViewController(viewModel: ThreadDisappearingMessagesViewModel( let viewController = SessionTableViewController(viewModel: ThreadDisappearingMessagesViewModel(
@ -61,6 +45,26 @@ extension ConversationVC:
break break
} }
} }
@objc func openSettings() {
let viewController = SessionTableViewController(viewModel: ThreadSettingsViewModel(
threadId: self.viewModel.threadData.threadId,
threadVariant: self.viewModel.threadData.threadVariant,
didTriggerSearch: { [weak self] in
DispatchQueue.main.async {
self?.showSearchUI()
self?.popAllConversationSettingsViews {
// Note: Without this delay the search bar doesn't show
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self?.searchController.uiSearchController.searchBar.becomeFirstResponder()
}
}
}
}
)
)
navigationController?.pushViewController(viewController, animated: true)
}
// MARK: - ScrollToBottomButtonDelegate // MARK: - ScrollToBottomButtonDelegate
@ -452,13 +456,6 @@ extension ConversationVC:
body: text, body: text,
timestampMs: sentTimestampMs, timestampMs: sentTimestampMs,
hasMention: Interaction.isUserMentioned(db, threadId: threadId, body: text), hasMention: Interaction.isUserMentioned(db, threadId: threadId, body: text),
// No matter the disappearing message type is D.A.R or D.A.S, it is the same on the sender's side
expiresInSeconds: try? DisappearingMessagesConfiguration
.select(.durationSeconds)
.filter(id: threadId)
.filter(DisappearingMessagesConfiguration.Columns.isEnabled == true)
.asRequest(of: TimeInterval.self)
.fetchOne(db),
linkPreviewUrl: linkPreviewDraft?.urlString linkPreviewUrl: linkPreviewDraft?.urlString
).inserted(db) ).inserted(db)
@ -575,13 +572,7 @@ extension ConversationVC:
variant: .standardOutgoing, variant: .standardOutgoing,
body: text, body: text,
timestampMs: sentTimestampMs, timestampMs: sentTimestampMs,
hasMention: Interaction.isUserMentioned(db, threadId: threadId, body: text), hasMention: Interaction.isUserMentioned(db, threadId: threadId, body: text)
expiresInSeconds: try? DisappearingMessagesConfiguration
.select(.durationSeconds)
.filter(id: threadId)
.filter(DisappearingMessagesConfiguration.Columns.isEnabled == true)
.asRequest(of: TimeInterval.self)
.fetchOne(db)
).inserted(db) ).inserted(db)
try MessageSender.send( try MessageSender.send(

@ -239,7 +239,7 @@ class ThreadDisappearingMessagesViewModel: SessionTableViewModel<ThreadDisappear
SectionModel( SectionModel(
model: .timer, model: .timer,
elements: DisappearingMessagesConfiguration elements: DisappearingMessagesConfiguration
.validDurationsSeconds(currentSelection.type ?? .disappearAfterRead) .validDurationsSeconds(currentSelection.type ?? .disappearAfterSend)
.map { duration in .map { duration in
let title: String = duration.formatted(format: .long) let title: String = duration.formatted(format: .long)

@ -533,13 +533,7 @@ class NotificationActionHandler {
variant: .standardOutgoing, variant: .standardOutgoing,
body: replyText, body: replyText,
timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000)), timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000)),
hasMention: Interaction.isUserMentioned(db, threadId: threadId, body: replyText), hasMention: Interaction.isUserMentioned(db, threadId: threadId, body: replyText)
expiresInSeconds: try? DisappearingMessagesConfiguration
.select(.durationSeconds)
.filter(id: threadId)
.filter(DisappearingMessagesConfiguration.Columns.isEnabled == true)
.asRequest(of: TimeInterval.self)
.fetchOne(db)
).inserted(db) ).inserted(db)
try Interaction.markAsRead( try Interaction.markAsRead(

@ -187,6 +187,7 @@ extension DisappearingMessagesConfiguration {
switch type { switch type {
case .disappearAfterRead: case .disappearAfterRead:
return [ return [
60, // TODO: remove this, for test purpose only
(5 * 60), (5 * 60),
(1 * 60 * 60), (1 * 60 * 60),
(12 * 60 * 60), (12 * 60 * 60),
@ -196,6 +197,7 @@ extension DisappearingMessagesConfiguration {
] ]
case .disappearAfterSend: case .disappearAfterSend:
return [ return [
60, // TODO: remove this, for test purpose only
(12 * 60 * 60), (12 * 60 * 60),
(24 * 60 * 60), (24 * 60 * 60),
(7 * 24 * 60 * 60), (7 * 24 * 60 * 60),

@ -102,15 +102,27 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
switch self { switch self {
case .standardIncoming: return true case .standardIncoming: return true
case .infoCall: return true case .infoCall: return true
case .infoDisappearingMessagesUpdate, .infoScreenshotNotification, .infoMediaSavedNotification: return true
case .standardOutgoing, .standardIncomingDeleted: return false case .standardOutgoing, .standardIncomingDeleted: return false
case .infoClosedGroupCreated, .infoClosedGroupUpdated, .infoClosedGroupCurrentUserLeft, case .infoClosedGroupCreated, .infoClosedGroupUpdated, .infoClosedGroupCurrentUserLeft,
.infoDisappearingMessagesUpdate, .infoScreenshotNotification, .infoMediaSavedNotification,
.infoMessageRequestAccepted: .infoMessageRequestAccepted:
return false return false
} }
} }
fileprivate var shouldFollowDisappearingMessagesConfiguration: Bool {
switch self {
case .standardIncoming, .standardOutgoing,
.infoCall,
.infoDisappearingMessagesUpdate,
.infoScreenshotNotification, .infoMediaSavedNotification:
return true
default: return false
}
}
} }
/// The `id` value is auto incremented by the database, if the `Interaction` hasn't been inserted into /// The `id` value is auto incremented by the database, if the `Interaction` hasn't been inserted into
@ -170,12 +182,12 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
public let hasMention: Bool public let hasMention: Bool
/// The number of seconds until this message should expire /// The number of seconds until this message should expire
public let expiresInSeconds: TimeInterval? public var expiresInSeconds: TimeInterval?
/// The timestamp in milliseconds since 1970 at which this messages expiration timer started counting /// The timestamp in milliseconds since 1970 at which this messages expiration timer started counting
/// down (this is stored in order to allow the `expiresInSeconds` value to be updated before a /// down (this is stored in order to allow the `expiresInSeconds` value to be updated before a
/// message has expired) /// message has expired)
public let expiresStartedAtMs: Double? public var expiresStartedAtMs: Double?
/// This value is the url for the link preview for this interaction /// This value is the url for the link preview for this interaction
/// ///
@ -320,6 +332,17 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
// Automatically mark interactions which can't be unread as read so the unread count // Automatically mark interactions which can't be unread as read so the unread count
// isn't impacted // isn't impacted
self.wasRead = (self.wasRead || !self.variant.canBeUnread) self.wasRead = (self.wasRead || !self.variant.canBeUnread)
// Automatically add disapeparing messages configuration
if self.variant.shouldFollowDisappearingMessagesConfiguration,
let disappearingMessagesConfiguration = try? DisappearingMessagesConfiguration.fetchOne(db, id: self.threadId),
disappearingMessagesConfiguration.isEnabled
{
self.expiresInSeconds = disappearingMessagesConfiguration.durationSeconds
if disappearingMessagesConfiguration.type == .disappearAfterSend {
self.expiresStartedAtMs = Double(self.timestampMs)
}
}
} }
public func aroundInsert(_ db: Database, insert: () throws -> InsertionSuccess) throws { public func aroundInsert(_ db: Database, insert: () throws -> InsertionSuccess) throws {

@ -91,14 +91,6 @@ extension MessageReceiver {
if let interactionId: Int64 = try handleEmojiReactIfNeeded(db, message: message, associatedWithProto: proto, sender: sender, messageSentTimestamp: messageSentTimestamp, openGroupId: openGroupId, thread: thread) { if let interactionId: Int64 = try handleEmojiReactIfNeeded(db, message: message, associatedWithProto: proto, sender: sender, messageSentTimestamp: messageSentTimestamp, openGroupId: openGroupId, thread: thread) {
return interactionId return interactionId
} }
// Retrieve the disappearing messages config to set the 'expiresInSeconds' value
// accoring to the config
let disappearingMessagesConfiguration: DisappearingMessagesConfiguration = (try? thread.disappearingMessagesConfiguration.fetchOne(db))
.defaulting(to: DisappearingMessagesConfiguration.defaultWith(thread.id))
let expiresStartedAtMs: Double? = (disappearingMessagesConfiguration.isEnabled && disappearingMessagesConfiguration.type == .disappearAfterSend) ? Double(message.sentTimestamp ?? 0) : nil
// Try to insert the interaction // Try to insert the interaction
// //
// Note: There are now a number of unique constraints on the database which // Note: There are now a number of unique constraints on the database which
@ -121,12 +113,6 @@ extension MessageReceiver {
body: message.text, body: message.text,
quoteAuthorId: dataMessage.quote?.author quoteAuthorId: dataMessage.quote?.author
), ),
// Note: Ensure we don't ever expire open group messages
expiresInSeconds: (disappearingMessagesConfiguration.isEnabled && message.openGroupServerMessageId == nil ?
disappearingMessagesConfiguration.durationSeconds :
nil
),
expiresStartedAtMs: expiresStartedAtMs,
// OpenGroupInvitations are stored as LinkPreview's in the database // OpenGroupInvitations are stored as LinkPreview's in the database
linkPreviewUrl: (message.linkPreview?.url ?? message.openGroupInvitation?.url), linkPreviewUrl: (message.linkPreview?.url ?? message.openGroupInvitation?.url),
// Keep track of the open group server message ID message ID relationship // Keep track of the open group server message ID message ID relationship

@ -356,6 +356,9 @@ public enum MessageReceiver {
lastChangeTimestampMs: protoLastChangeTimestampMs lastChangeTimestampMs: protoLastChangeTimestampMs
) )
let expireInSeconds: TimeInterval? = (remoteConfig.isEnabled && message.openGroupServerMessageId == nil) ? remoteConfig.durationSeconds : nil
let expiresStartedAtMs: Double? = (remoteConfig.isEnabled && remoteConfig.type == .disappearAfterSend) ? Double(message.sentTimestamp ?? 0) : nil
_ = try Interaction( _ = try Interaction(
serverHash: nil, // Intentionally null so sync messages are seen as duplicates serverHash: nil, // Intentionally null so sync messages are seen as duplicates
threadId: threadId, threadId: threadId,
@ -368,7 +371,9 @@ public enum MessageReceiver {
), ),
isPreviousOff: !localConfig.isEnabled isPreviousOff: !localConfig.isEnabled
), ),
timestampMs: protoLastChangeTimestampMs timestampMs: protoLastChangeTimestampMs,
expiresInSeconds: expireInSeconds,
expiresStartedAtMs: expiresStartedAtMs
).inserted(db) ).inserted(db)
try remoteConfig.save(db) try remoteConfig.save(db)

@ -198,12 +198,6 @@ final class ThreadPickerVC: UIViewController, UITableViewDataSource, UITableView
body: body, body: body,
timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000)), timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000)),
hasMention: Interaction.isUserMentioned(db, threadId: threadId, body: body), hasMention: Interaction.isUserMentioned(db, threadId: threadId, body: body),
expiresInSeconds: try? DisappearingMessagesConfiguration
.select(.durationSeconds)
.filter(id: threadId)
.filter(DisappearingMessagesConfiguration.Columns.isEnabled == true)
.asRequest(of: TimeInterval.self)
.fetchOne(db),
linkPreviewUrl: (isSharingUrl ? attachments.first?.linkPreviewDraft?.urlString : nil) linkPreviewUrl: (isSharingUrl ? attachments.first?.linkPreviewDraft?.urlString : nil)
).inserted(db) ).inserted(db)

Loading…
Cancel
Save