WIP: make group leaving a job
This commit is contained in:
parent
eed8b1dfcb
commit
cea2e1522d
|
@ -451,11 +451,12 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
|
|||
Storage.shared
|
||||
.writeAsync { db in
|
||||
if !updatedMemberIds.contains(userPublicKey) {
|
||||
return try MessageSender
|
||||
.leave(db, groupPublicKey: threadId)
|
||||
.map { (_, error) in
|
||||
if let error: Error = error { throw error }
|
||||
}
|
||||
try MessageSender.leave(
|
||||
db,
|
||||
groupPublicKey: threadId,
|
||||
deleteThread: false
|
||||
)
|
||||
return Promise.value(())
|
||||
}
|
||||
|
||||
return try MessageSender.update(
|
||||
|
|
|
@ -405,7 +405,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
|
|||
),
|
||||
onTap: { [weak self] in
|
||||
dependencies.storage.writeAsync { db in
|
||||
try MessageSender.leave(db, groupPublicKey: threadId)
|
||||
try MessageSender.leave(db, groupPublicKey: threadId, deleteThread: false)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -305,28 +305,11 @@ public class HomeViewModel {
|
|||
Storage.shared.writeAsync { db in
|
||||
switch threadVariant {
|
||||
case .closedGroup:
|
||||
try MessageSender
|
||||
.leave(db, groupPublicKey: threadId)
|
||||
.done { (interactionId, error) in
|
||||
Storage.shared.writeAsync { db in
|
||||
if let _ = error {
|
||||
try Interaction
|
||||
.filter(id: interactionId)
|
||||
.updateAll(
|
||||
db,
|
||||
[
|
||||
Interaction.Columns.variant.set(to: Interaction.Variant.infoClosedGroupCurrentUserErrorLeaving),
|
||||
Interaction.Columns.body.set(to: "group_unable_to_leave".localized())
|
||||
]
|
||||
)
|
||||
} else {
|
||||
_ = try SessionThread
|
||||
.filter(id: threadId)
|
||||
.deleteAll(db)
|
||||
}
|
||||
}
|
||||
}
|
||||
.retainUntilComplete()
|
||||
try MessageSender.leave(
|
||||
db,
|
||||
groupPublicKey: threadId,
|
||||
deleteThread: true
|
||||
)
|
||||
|
||||
case .openGroup:
|
||||
OpenGroupManager.shared.delete(db, openGroupId: threadId)
|
||||
|
|
|
@ -46,5 +46,6 @@ public enum SNMessagingKit { // Just to make the external API nice
|
|||
JobRunner.add(executor: SendReadReceiptsJob.self, for: .sendReadReceipts)
|
||||
JobRunner.add(executor: AttachmentDownloadJob.self, for: .attachmentDownload)
|
||||
JobRunner.add(executor: AttachmentUploadJob.self, for: .attachmentUpload)
|
||||
JobRunner.add(executor: GroupLeavingJob.self, for: .groupLeaving)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,8 @@ public enum GroupLeavingJob: JobExecutor {
|
|||
{
|
||||
guard
|
||||
let detailsData: Data = job.details,
|
||||
let details: Details = try? JSONDecoder().decode(Details.self, from: detailsData)
|
||||
let details: Details = try? JSONDecoder().decode(Details.self, from: detailsData),
|
||||
let interactionId: Int64 = job.interactionId
|
||||
else {
|
||||
failure(job, JobRunnerError.missingRequiredDetails, false)
|
||||
return
|
||||
|
@ -44,7 +45,7 @@ public enum GroupLeavingJob: JobExecutor {
|
|||
message: ClosedGroupControlMessage(
|
||||
kind: .memberLeft
|
||||
),
|
||||
interactionId: details.infoMessageInteractionId,
|
||||
interactionId: interactionId,
|
||||
in: thread
|
||||
)
|
||||
}
|
||||
|
@ -66,7 +67,7 @@ public enum GroupLeavingJob: JobExecutor {
|
|||
)
|
||||
|
||||
try Interaction
|
||||
.filter(id: details.infoMessageInteractionId)
|
||||
.filter(id: interactionId)
|
||||
.updateAll(
|
||||
db,
|
||||
[
|
||||
|
@ -94,7 +95,7 @@ public enum GroupLeavingJob: JobExecutor {
|
|||
.deleteAll(db)
|
||||
}
|
||||
|
||||
if details.deleteThreadAfterSuccess {
|
||||
if details.deleteThread {
|
||||
_ = try SessionThread
|
||||
.filter(id: thread.id)
|
||||
.deleteAll(db)
|
||||
|
@ -105,7 +106,7 @@ public enum GroupLeavingJob: JobExecutor {
|
|||
.catch(on: queue) { error in
|
||||
Storage.shared.write { db in
|
||||
try Interaction
|
||||
.filter(id: details.infoMessageInteractionId)
|
||||
.filter(id: job.interactionId)
|
||||
.updateAll(
|
||||
db,
|
||||
[
|
||||
|
@ -125,25 +126,21 @@ public enum GroupLeavingJob: JobExecutor {
|
|||
extension GroupLeavingJob {
|
||||
public struct Details: Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case infoMessageInteractionId
|
||||
case groupPublicKey
|
||||
case deleteThreadAfterSuccess
|
||||
case deleteThread
|
||||
}
|
||||
|
||||
public let infoMessageInteractionId: Int64
|
||||
public let groupPublicKey: String
|
||||
public let deleteThreadAfterSuccess: Bool
|
||||
public let deleteThread: Bool
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
public init(
|
||||
infoMessageInteractionId: Int64,
|
||||
groupPublicKey: String,
|
||||
deleteThreadAfterSuccess: Bool
|
||||
deleteThread: Bool
|
||||
) {
|
||||
self.infoMessageInteractionId = infoMessageInteractionId
|
||||
self.groupPublicKey = groupPublicKey
|
||||
self.deleteThreadAfterSuccess = deleteThreadAfterSuccess
|
||||
self.deleteThread = deleteThread
|
||||
}
|
||||
|
||||
// MARK: - Codable
|
||||
|
@ -152,18 +149,16 @@ extension GroupLeavingJob {
|
|||
let container: KeyedDecodingContainer<CodingKeys> = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
self = Details(
|
||||
infoMessageInteractionId: try container.decode(Int64.self, forKey: .infoMessageInteractionId),
|
||||
groupPublicKey: try container.decode(String.self, forKey: .groupPublicKey),
|
||||
deleteThreadAfterSuccess: try container.decode(Bool.self, forKey: .deleteThreadAfterSuccess)
|
||||
deleteThread: try container.decode(Bool.self, forKey: .deleteThread)
|
||||
)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container: KeyedEncodingContainer<CodingKeys> = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
try container.encode(infoMessageInteractionId, forKey: .infoMessageInteractionId)
|
||||
try container.encode(groupPublicKey, forKey: .groupPublicKey)
|
||||
try container.encode(deleteThreadAfterSuccess, forKey: .deleteThreadAfterSuccess)
|
||||
try container.encode(deleteThread, forKey: .deleteThread)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -478,13 +478,9 @@ extension MessageSender {
|
|||
/// unregisters from push notifications.
|
||||
///
|
||||
/// The returned promise is fulfilled when the `MEMBER_LEFT` message has been sent to the group.
|
||||
public static func leave(_ db: Database, groupPublicKey: String) throws -> Promise<(Int64, Error?)> {
|
||||
public static func leave(_ db: Database, groupPublicKey: String, deleteThread: Bool) throws {
|
||||
guard let thread: SessionThread = try? SessionThread.fetchOne(db, id: groupPublicKey) else {
|
||||
SNLog("Can't leave nonexistent closed group.")
|
||||
return Promise(error: MessageSenderError.noThread)
|
||||
}
|
||||
guard let closedGroup: ClosedGroup = try? thread.closedGroup.fetchOne(db) else {
|
||||
return Promise(error: MessageSenderError.invalidClosedGroupUpdate)
|
||||
return
|
||||
}
|
||||
|
||||
let userPublicKey: String = getUserHexEncodedPublicKey(db)
|
||||
|
@ -498,78 +494,18 @@ extension MessageSender {
|
|||
timestampMs: SnodeAPI.currentOffsetTimestampMs()
|
||||
).inserted(db)
|
||||
|
||||
guard let interactionId: Int64 = interaction.id else {
|
||||
throw StorageError.objectNotSaved
|
||||
}
|
||||
|
||||
// Send the update to the group
|
||||
let (promise, seal) = Promise<(Int64, Error?)>.pending()
|
||||
do {
|
||||
try MessageSender
|
||||
.sendNonDurably(
|
||||
db,
|
||||
message: ClosedGroupControlMessage(
|
||||
kind: .memberLeft
|
||||
),
|
||||
interactionId: interactionId,
|
||||
in: thread
|
||||
JobRunner.add(
|
||||
db,
|
||||
job: Job(
|
||||
variant: .groupLeaving,
|
||||
threadId: thread.id,
|
||||
interactionId: interaction.id,
|
||||
details: GroupLeavingJob.Details(
|
||||
groupPublicKey: groupPublicKey,
|
||||
deleteThread: deleteThread
|
||||
)
|
||||
.done {
|
||||
// Remove the group from the database and unsubscribe from PNs
|
||||
ClosedGroupPoller.shared.stopPolling(for: groupPublicKey)
|
||||
|
||||
Storage.shared.write { db in
|
||||
try closedGroup
|
||||
.keyPairs
|
||||
.deleteAll(db)
|
||||
|
||||
let _ = PushNotificationAPI.performOperation(
|
||||
.unsubscribe,
|
||||
for: groupPublicKey,
|
||||
publicKey: userPublicKey
|
||||
)
|
||||
|
||||
try Interaction
|
||||
.filter(id: interactionId)
|
||||
.updateAll(
|
||||
db,
|
||||
[
|
||||
Interaction.Columns.variant.set(to: Interaction.Variant.infoClosedGroupCurrentUserLeft),
|
||||
Interaction.Columns.body.set(to: "GROUP_YOU_LEFT".localized())
|
||||
]
|
||||
)
|
||||
|
||||
// Update the group (if the admin leaves the group is disbanded)
|
||||
let wasAdminUser: Bool = try GroupMember
|
||||
.filter(GroupMember.Columns.groupId == thread.id)
|
||||
.filter(GroupMember.Columns.profileId == userPublicKey)
|
||||
.filter(GroupMember.Columns.role == GroupMember.Role.admin)
|
||||
.isNotEmpty(db)
|
||||
|
||||
if wasAdminUser {
|
||||
try GroupMember
|
||||
.filter(GroupMember.Columns.groupId == thread.id)
|
||||
.deleteAll(db)
|
||||
}
|
||||
else {
|
||||
try GroupMember
|
||||
.filter(GroupMember.Columns.groupId == thread.id)
|
||||
.filter(GroupMember.Columns.profileId == userPublicKey)
|
||||
.deleteAll(db)
|
||||
}
|
||||
}
|
||||
seal.fulfill((interactionId, nil))
|
||||
}
|
||||
.catch { error in
|
||||
seal.fulfill((interactionId, error))
|
||||
}
|
||||
}
|
||||
catch {
|
||||
seal.fulfill((interactionId, error))
|
||||
}
|
||||
|
||||
// Return
|
||||
return promise
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -763,26 +763,3 @@ public final class MessageSender {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Objective-C Support
|
||||
|
||||
// FIXME: Remove when possible
|
||||
|
||||
@objc(SMKMessageSender)
|
||||
public class SMKMessageSender: NSObject {
|
||||
@objc(leaveClosedGroupWithPublicKey:)
|
||||
public static func objc_leave(_ groupPublicKey: String) -> AnyPromise {
|
||||
let promise = Storage.shared.writeAsync { db in
|
||||
try MessageSender.leave(db, groupPublicKey: groupPublicKey)
|
||||
}
|
||||
|
||||
return AnyPromise.from(promise)
|
||||
}
|
||||
|
||||
@objc(forceSyncConfigurationNow)
|
||||
public static func objc_forceSyncConfigurationNow() {
|
||||
Storage.shared.write { db in
|
||||
try MessageSender.syncConfiguration(db, forceSyncNow: true).retainUntilComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,8 @@ public final class JobRunner {
|
|||
jobVariants.remove(.attachmentUpload),
|
||||
jobVariants.remove(.messageSend),
|
||||
jobVariants.remove(.notifyPushServer),
|
||||
jobVariants.remove(.sendReadReceipts)
|
||||
jobVariants.remove(.sendReadReceipts),
|
||||
jobVariants.remove(.groupLeaving)
|
||||
].compactMap { $0 }
|
||||
)
|
||||
let messageReceiveQueue: JobQueue = JobQueue(
|
||||
|
|
Loading…
Reference in New Issue