use delete action for group that current user is no longer in

pull/799/head
ryanzhao 3 years ago
parent 7f24097343
commit 36748a81c6

@ -764,6 +764,30 @@ final class HomeVC: BaseVC, UITableViewDataSource, UITableViewDelegate, SeedRemi
return UISwipeActionsConfiguration(actions: [ delete, mute, pin ]) return UISwipeActionsConfiguration(actions: [ delete, mute, pin ])
case .openGroup, .closedGroup: case .openGroup, .closedGroup:
if threadViewModel.currentUserIsClosedGroupMember == false {
let delete: UIContextualAction = UIContextualAction(
title: "TXT_DELETE_TITLE".localized(),
icon: UIImage(named: "icon_bin")?.resizedImage(to: CGSize(width: Values.mediumFontSize, height: Values.mediumFontSize)),
iconHeight: Values.mediumFontSize,
themeTintColor: .white,
themeBackgroundColor: .conversationButton_swipeDestructive,
side: .trailing,
actionIndex: 2,
indexPath: indexPath,
tableView: tableView
) { [weak self] _, _, completionHandler in
self?.viewModel.delete(
threadId: threadViewModel.threadId,
threadVariant: threadViewModel.threadVariant,
force: true
)
completionHandler(true)
}
return UISwipeActionsConfiguration(actions: [ delete, mute, pin ])
}
let leave: UIContextualAction = UIContextualAction( let leave: UIContextualAction = UIContextualAction(
title: "LEAVE_BUTTON_TITLE".localized(), title: "LEAVE_BUTTON_TITLE".localized(),
icon: UIImage(systemName: "rectangle.portrait.and.arrow.right"), icon: UIImage(systemName: "rectangle.portrait.and.arrow.right"),

@ -301,23 +301,42 @@ public class HomeViewModel {
// MARK: - Functions // MARK: - Functions
public func delete(threadId: String, threadVariant: SessionThread.Variant) { public func delete(threadId: String, threadVariant: SessionThread.Variant, force: Bool = false) {
func delete(_ db: Database, threadId: String) throws {
_ = try SessionThread
.filter(id: threadId)
.deleteAll(db)
}
Storage.shared.writeAsync { db in Storage.shared.writeAsync { db in
switch threadVariant { switch threadVariant {
case .closedGroup: case .closedGroup:
if force {
if let thread: SessionThread = try? SessionThread.fetchOne(db, id: threadId),
let closedGroup: ClosedGroup = try? thread.closedGroup.fetchOne(db)
{
try MessageSender.performClosedGroupCleanUp(
db,
for: closedGroup,
in: thread
)
}
try delete(db, threadId: threadId)
} else {
try MessageSender.leave( try MessageSender.leave(
db, db,
groupPublicKey: threadId, groupPublicKey: threadId,
deleteThread: true deleteThread: true
) )
}
case .openGroup: case .openGroup:
OpenGroupManager.shared.delete(db, openGroupId: threadId) OpenGroupManager.shared.delete(db, openGroupId: threadId)
_ = try SessionThread try delete(db, threadId: threadId)
.filter(id: threadId)
.deleteAll(db)
default: break default:
try delete(db, threadId: threadId)
} }
} }
} }

@ -50,21 +50,8 @@ public enum GroupLeavingJob: JobExecutor {
) )
} }
.done(on: queue) { _ in .done(on: queue) { _ in
// Remove the group from the database and unsubscribe from PNs
ClosedGroupPoller.shared.stopPolling(for: details.groupPublicKey)
Storage.shared.writeAsync { db in Storage.shared.writeAsync { db in
let userPublicKey: String = getUserHexEncodedPublicKey(db) try MessageSender.performClosedGroupCleanUp(db, for: closedGroup, in: thread)
try closedGroup
.keyPairs
.deleteAll(db)
let _ = PushNotificationAPI.performOperation(
.unsubscribe,
for: details.groupPublicKey,
publicKey: userPublicKey
)
try Interaction try Interaction
.filter(id: interactionId) .filter(id: interactionId)
@ -76,25 +63,6 @@ public enum GroupLeavingJob: JobExecutor {
] ]
) )
// 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)
}
if details.deleteThread { if details.deleteThread {
_ = try SessionThread _ = try SessionThread
.filter(id: thread.id) .filter(id: thread.id)

@ -582,4 +582,40 @@ extension MessageSender {
} }
catch {} catch {}
} }
/// Remove the group from the database and unsubscribe from PNs
public static func performClosedGroupCleanUp(_ db: Database, for closedGroup: ClosedGroup, in thread: SessionThread) throws {
ClosedGroupPoller.shared.stopPolling(for: closedGroup.publicKey)
let userPublicKey: String = getUserHexEncodedPublicKey(db)
try closedGroup
.keyPairs
.deleteAll(db)
let _ = PushNotificationAPI.performOperation(
.unsubscribe,
for: closedGroup.publicKey,
publicKey: userPublicKey
)
// 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)
}
}
} }

@ -457,6 +457,9 @@ public extension SessionThreadViewModel {
let interactionAttachmentAttachmentIdColumnLiteral: SQL = SQL(stringLiteral: InteractionAttachment.Columns.attachmentId.name) let interactionAttachmentAttachmentIdColumnLiteral: SQL = SQL(stringLiteral: InteractionAttachment.Columns.attachmentId.name)
let interactionAttachmentInteractionIdColumnLiteral: SQL = SQL(stringLiteral: InteractionAttachment.Columns.interactionId.name) let interactionAttachmentInteractionIdColumnLiteral: SQL = SQL(stringLiteral: InteractionAttachment.Columns.interactionId.name)
let interactionAttachmentAlbumIndexColumnLiteral: SQL = SQL(stringLiteral: InteractionAttachment.Columns.albumIndex.name) let interactionAttachmentAlbumIndexColumnLiteral: SQL = SQL(stringLiteral: InteractionAttachment.Columns.albumIndex.name)
let groupMemberProfileIdColumnLiteral: SQL = SQL(stringLiteral: GroupMember.Columns.profileId.name)
let groupMemberRoleColumnLiteral: SQL = SQL(stringLiteral: GroupMember.Columns.role.name)
let groupMemberGroupIdColumnLiteral: SQL = SQL(stringLiteral: GroupMember.Columns.groupId.name)
/// **Note:** The `numColumnsBeforeProfiles` value **MUST** match the number of fields before /// **Note:** The `numColumnsBeforeProfiles` value **MUST** match the number of fields before
/// the `ViewModel.contactProfileKey` entry below otherwise the query will fail to /// the `ViewModel.contactProfileKey` entry below otherwise the query will fail to
@ -464,7 +467,7 @@ public extension SessionThreadViewModel {
/// ///
/// Explicitly set default values for the fields ignored for search results /// Explicitly set default values for the fields ignored for search results
let numColumnsBeforeProfiles: Int = 12 let numColumnsBeforeProfiles: Int = 12
let numColumnsBetweenProfilesAndAttachmentInfo: Int = 11 // The attachment info columns will be combined let numColumnsBetweenProfilesAndAttachmentInfo: Int = 12 // The attachment info columns will be combined
let request: SQLRequest<ViewModel> = """ let request: SQLRequest<ViewModel> = """
SELECT SELECT
@ -488,7 +491,8 @@ public extension SessionThreadViewModel {
\(ViewModel.closedGroupProfileBackKey).*, \(ViewModel.closedGroupProfileBackKey).*,
\(ViewModel.closedGroupProfileBackFallbackKey).*, \(ViewModel.closedGroupProfileBackFallbackKey).*,
\(closedGroup[.name]) AS \(ViewModel.closedGroupNameKey), \(closedGroup[.name]) AS \(ViewModel.closedGroupNameKey),
(\(groupMember[.profileId]) IS NOT NULL) AS \(ViewModel.currentUserIsClosedGroupAdminKey), (\(ViewModel.currentUserIsClosedGroupMemberKey).profileId IS NOT NULL) AS \(ViewModel.currentUserIsClosedGroupMemberKey),
(\(ViewModel.currentUserIsClosedGroupAdminKey).profileId IS NOT NULL) AS \(ViewModel.currentUserIsClosedGroupAdminKey),
\(openGroup[.name]) AS \(ViewModel.openGroupNameKey), \(openGroup[.name]) AS \(ViewModel.openGroupNameKey),
\(openGroup[.imageData]) AS \(ViewModel.openGroupProfilePictureDataKey), \(openGroup[.imageData]) AS \(ViewModel.openGroupProfilePictureDataKey),
@ -563,10 +567,15 @@ public extension SessionThreadViewModel {
LEFT JOIN \(Profile.self) AS \(ViewModel.contactProfileKey) ON \(ViewModel.contactProfileKey).\(profileIdColumnLiteral) = \(thread[.id]) LEFT JOIN \(Profile.self) AS \(ViewModel.contactProfileKey) ON \(ViewModel.contactProfileKey).\(profileIdColumnLiteral) = \(thread[.id])
LEFT JOIN \(OpenGroup.self) ON \(openGroup[.threadId]) = \(thread[.id]) LEFT JOIN \(OpenGroup.self) ON \(openGroup[.threadId]) = \(thread[.id])
LEFT JOIN \(ClosedGroup.self) ON \(closedGroup[.threadId]) = \(thread[.id]) LEFT JOIN \(ClosedGroup.self) ON \(closedGroup[.threadId]) = \(thread[.id])
LEFT JOIN \(GroupMember.self) ON ( LEFT JOIN \(GroupMember.self) AS \(ViewModel.currentUserIsClosedGroupMemberKey) ON (
\(SQL("\(groupMember[.role]) = \(GroupMember.Role.admin)")) AND \(SQL("\(ViewModel.currentUserIsClosedGroupMemberKey).\(groupMemberRoleColumnLiteral) != \(GroupMember.Role.zombie)")) AND
\(groupMember[.groupId]) = \(closedGroup[.threadId]) AND \(ViewModel.currentUserIsClosedGroupMemberKey).\(groupMemberGroupIdColumnLiteral) = \(closedGroup[.threadId]) AND
\(SQL("\(groupMember[.profileId]) = \(userPublicKey)")) \(SQL("\(ViewModel.currentUserIsClosedGroupMemberKey).\(groupMemberProfileIdColumnLiteral) = \(userPublicKey)"))
)
LEFT JOIN \(GroupMember.self) AS \(ViewModel.currentUserIsClosedGroupAdminKey) ON (
\(SQL("\(ViewModel.currentUserIsClosedGroupAdminKey).\(groupMemberRoleColumnLiteral) = \(GroupMember.Role.admin)")) AND
\(ViewModel.currentUserIsClosedGroupAdminKey).\(groupMemberGroupIdColumnLiteral) = \(closedGroup[.threadId]) AND
\(SQL("\(ViewModel.currentUserIsClosedGroupAdminKey).\(groupMemberProfileIdColumnLiteral) = \(userPublicKey)"))
) )
LEFT JOIN \(Profile.self) AS \(ViewModel.closedGroupProfileFrontKey) ON ( LEFT JOIN \(Profile.self) AS \(ViewModel.closedGroupProfileFrontKey) ON (

Loading…
Cancel
Save