Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/attachment #952

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Mixin.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,7 @@
947E0659279867870002669B /* PINIteratorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 947E0658279867870002669B /* PINIteratorTest.swift */; };
947F4AD625866D6C00B0A5F9 /* InitializeFTSJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 947F4AD525866D6C00B0A5F9 /* InitializeFTSJob.swift */; };
94812DDA26E082C400213F79 /* mixin_condensed.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94812DD926E082C400213F79 /* mixin_condensed.otf */; };
948983B1284E66C00065DC5D /* ConversationCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948983B0284E66C00065DC5D /* ConversationCleaner.swift */; };
9489E3A025C5B150000319F8 /* AcknowledgementsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9489E39F25C5B150000319F8 /* AcknowledgementsViewController.swift */; };
9492285F25DFB7D60000A19F /* MinimizedPlaylistViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9492285E25DFB7D60000A19F /* MinimizedPlaylistViewController.swift */; };
9492286425DFB7EF0000A19F /* MinimizedPlaylistView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9492286325DFB7EF0000A19F /* MinimizedPlaylistView.xib */; };
Expand Down Expand Up @@ -1685,6 +1686,7 @@
947F4AD525866D6C00B0A5F9 /* InitializeFTSJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitializeFTSJob.swift; sourceTree = "<group>"; };
94812DD926E082C400213F79 /* mixin_condensed.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = mixin_condensed.otf; sourceTree = "<group>"; };
94841CC72797D89500B3593B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
948983B0284E66C00065DC5D /* ConversationCleaner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationCleaner.swift; sourceTree = "<group>"; };
9489E39F25C5B150000319F8 /* AcknowledgementsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AcknowledgementsViewController.swift; sourceTree = "<group>"; };
9492285E25DFB7D60000A19F /* MinimizedPlaylistViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MinimizedPlaylistViewController.swift; sourceTree = "<group>"; };
9492286325DFB7EF0000A19F /* MinimizedPlaylistView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MinimizedPlaylistView.xib; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2436,6 +2438,7 @@
E0A14D3B2372F0340044D131 /* GroupProfileViewController.swift */,
7B5E9B3F243700CD000AE24E /* ConversationCircleEditorViewController.swift */,
7CB2A57E27C386F0007D9DEE /* GroupsInCommonViewController.swift */,
948983B0284E66C00065DC5D /* ConversationCleaner.swift */,
);
path = Common;
sourceTree = "<group>";
Expand Down Expand Up @@ -4799,6 +4802,7 @@
7BC80A62221D1C07008586AD /* AssetTableHeaderView.swift in Sources */,
7B9553402243860C00CE95E6 /* PinValidationPresentationManager.swift in Sources */,
94046B93272DC28B007C1D4A /* GroupCallMembersManager.swift in Sources */,
948983B1284E66C00065DC5D /* ConversationCleaner.swift in Sources */,
7B4C6571242358D5003B78F9 /* LocationSearchNoResultView.swift in Sources */,
DF5D9F291F9C79E10036D5FD /* UIColorExtension.swift in Sources */,
DF0A0A5E24476EA000378B4F /* RefreshOffsetJob.swift in Sources */,
Expand Down
16 changes: 8 additions & 8 deletions Mixin/Service/Audio/Playlist/PlaylistManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,12 @@ class PlaylistManager: NSObject {
name: MessageDAO.didInsertMessageNotification,
object: nil)
notificationCenter.addObserver(self,
selector: #selector(messageDAOWillDeleteMessage(_:)),
name: MessageDAO.willDeleteMessageNotification,
selector: #selector(messageWillDelete(_:)),
name: DeleteMessageAttachmentWork.willDeleteNotification,
object: nil)
notificationCenter.addObserver(self,
selector: #selector(conversationDAOWillClearConversation(_:)),
name: ConversationDAO.willClearConversationNotification,
selector: #selector(conversationWillClean(_:)),
name: ConversationCleaner.willCleanNotification,
object: nil)
notificationCenter.addObserver(self,
selector: #selector(messageServiceWillRecallMessage(_:)),
Expand Down Expand Up @@ -773,8 +773,8 @@ extension PlaylistManager {
loadLaterItemsIfNeeded()
}

@objc private func messageDAOWillDeleteMessage(_ notification: Notification) {
guard let messageId = notification.userInfo?[MessageDAO.UserInfoKey.messageId] as? String else {
@objc private func messageWillDelete(_ notification: Notification) {
guard let messageId = notification.userInfo?[DeleteMessageAttachmentWork.messageIdUserInfoKey] as? String else {
return
}
guard case .conversation = source else {
Expand All @@ -783,8 +783,8 @@ extension PlaylistManager {
removeItem(with: messageId)
}

@objc private func conversationDAOWillClearConversation(_ notification: Notification) {
guard let id = notification.userInfo?[ConversationDAO.conversationIdUserInfoKey] as? String else {
@objc private func conversationWillClean(_ notification: Notification) {
guard let id = notification.userInfo?[ConversationCleaner.conversationIdUserInfoKey] as? String else {
return
}
guard case let .conversation(conversationId) = source, conversationId == id else {
Expand Down
3 changes: 2 additions & 1 deletion Mixin/Service/Job/AttachmentUploadJob.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ class AttachmentUploadJob: AttachmentLoadingJob {
return false
}
guard let fileUrl = fileUrl else {
MessageDAO.shared.deleteMessage(id: messageId)
let work = DeleteMessageAttachmentWork(message: message)
WorkManager.general.addWork(work)
return false
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,8 @@ class ConversationInputViewController: UIViewController {
self.deleteConversationButton.isBusy = false
}))
alert.addAction(UIAlertAction(title: R.string.localizable.delete_chat(), style: .destructive, handler: { (_) in
DispatchQueue.global().async { [weak self] in
ConversationDAO.shared.deleteChat(conversationId: conversationId)
DispatchQueue.main.async {
self?.navigationController?.backToHome()
}
ConversationCleaner.clean(conversationId: conversationId, intent: .delete) {
self.navigationController?.backToHome()
}
}))
present(alert, animated: true, completion: nil)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2706,9 +2706,11 @@ extension ConversationViewController {
guard let weakSelf = self, let indexPath = weakSelf.dataSource.indexPath(where: { $0.messageId == message.messageId }) else {
return
}
let (deleted, childMessageIds) = MessageDAO.shared.deleteMessage(id: message.messageId)
if deleted {
ReceiveMessageService.shared.stopRecallMessage(item: message, childMessageIds: childMessageIds)
MessageDAO.shared.delete(id: message.messageId, conversationId: message.conversationId, deleteTranscriptChildren: false) { db in
if DeleteMessageAttachmentWork.capableMessageCategories.contains(message.category) {
let work = DeleteMessageAttachmentWork(message: message)
WorkManager.general.addPersistableWork(work, alongsideTransactionWith: db)
}
}
DispatchQueue.main.sync {
_ = weakSelf.dataSource?.removeViewModel(at: indexPath)
Expand Down
77 changes: 77 additions & 0 deletions Mixin/UserInterface/Controllers/Common/ConversationCleaner.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import Foundation
import MixinServices
import GRDB

enum ConversationCleaner {

public static let willCleanNotification = Notification.Name("one.mixin.messenger.ConversationCleaner.willClean")
public static let conversationIdUserInfoKey = "cid"

enum Intent {
case delete
case clear
}

static func clean(conversationId: String, intent: Intent, completion: (() -> Void)? = nil) {
let hud = Hud()
hud.show(style: .busy, text: "", on: AppDelegate.current.mainWindow)
NotificationCenter.default.post(name: Self.willCleanNotification,
object: self,
userInfo: [Self.conversationIdUserInfoKey: conversationId])
DispatchQueue.global().async {
UserDatabase.current.write { db in
let categories = MessageCategory.allMediaCategoriesString.joined(separator: "', '")
let sql = "SELECT media_url, category FROM messages WHERE conversation_id = ? AND category IN ('\(categories)') AND media_url IS NOT NULL"
let attachments = try DeleteConversationAttachmentWork.Attachment.fetchAll(db, sql: sql, arguments: [conversationId])
let transcriptMessageIds = try MessageDAO.shared.getTranscriptMessageIds(conversationId: conversationId, database: db)
if !attachments.isEmpty || !transcriptMessageIds.isEmpty {
let work = DeleteConversationAttachmentWork(attachments: attachments, transcriptMessageIds: transcriptMessageIds)
WorkManager.general.addPersistableWork(work, alongsideTransactionWith: db)
}

try Message
.filter(Message.column(of: .conversationId) == conversationId)
.deleteAll(db)
try MessageMention
.filter(MessageMention.column(of: .conversationId) == conversationId)
.deleteAll(db)

switch intent {
case .delete:
try Conversation
.filter(Conversation.column(of: .conversationId) == conversationId)
.deleteAll(db)
try Participant
.filter(Participant.column(of: .conversationId) == conversationId)
.deleteAll(db)
try ParticipantSession
.filter(ParticipantSession.column(of: .conversationId) == conversationId)
.deleteAll(db)
case .clear:
try Conversation
.filter(Conversation.column(of: .conversationId) == conversationId)
.updateAll(db, [Conversation.column(of: .unseenMessageCount).set(to: 0)])
}

try ConversationDAO.shared.deleteFTSContent(with: conversationId, from: db)
try PinMessageDAO.shared.deleteAll(conversationId: conversationId, from: db)
db.afterNextTransactionCommit { (_) in
DispatchQueue.main.async {
switch intent {
case .delete:
NotificationCenter.default.post(name: conversationDidChangeNotification, object: nil)
hud.set(style: .notification, text: R.string.localizable.deleted())
case .clear:
let change = ConversationChange(conversationId: conversationId, action: .reload)
NotificationCenter.default.post(name: conversationDidChangeNotification, object: change)
hud.set(style: .notification, text: R.string.localizable.cleared())
}
hud.scheduleAutoHidden()
completion?()
}
}
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -207,21 +207,11 @@ extension GroupProfileViewController {
let conversationId = conversation.conversationId
let alert = UIAlertController(title: R.string.localizable.delete_group_chat_confirmation(conversation.name), message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: R.string.localizable.cancel(), style: .cancel, handler: nil))
alert.addAction(UIAlertAction(title: R.string.localizable.delete_chat(), style: .destructive, handler: { [weak self](_) in
let hud = Hud()
hud.show(style: .busy, text: "", on: AppDelegate.current.mainWindow)
DispatchQueue.global().async {
ConversationDAO.shared.deleteChat(conversationId: conversationId)
DispatchQueue.main.async {
guard let self = self else {
return
}
self.dismiss(animated: true) {
hud.set(style: .notification, text: R.string.localizable.done())
hud.scheduleAutoHidden()
if UIApplication.currentConversationId() == conversationId {
UIApplication.homeNavigationController?.backToHome()
}
alert.addAction(UIAlertAction(title: R.string.localizable.delete_chat(), style: .destructive, handler: { _ in
ConversationCleaner.clean(conversationId: conversationId, intent: .delete) {
self.dismiss(animated: true) {
if UIApplication.currentConversationId() == conversationId {
UIApplication.homeNavigationController?.backToHome()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,7 @@ extension ProfileViewController {
alert.addAction(UIAlertAction(title: R.string.localizable.cancel(), style: .cancel, handler: nil))
alert.addAction(UIAlertAction(title: R.string.localizable.clear_chat(), style: .destructive, handler: { (_) in
self.dismiss(animated: true, completion: nil)
DispatchQueue.global().async {
ConversationDAO.shared.clearChat(conversationId: conversationId)
DispatchQueue.main.async {
showAutoHiddenHud(style: .notification, text: R.string.localizable.cleared())
}
}
ConversationCleaner.clean(conversationId: conversationId, intent: .clear)
}))
present(alert, animated: true, completion: nil)
}
Expand Down
12 changes: 6 additions & 6 deletions Mixin/UserInterface/Controllers/Home/HomeViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ class HomeViewController: UIViewController {
if AppGroupUserDefaults.User.hasRecoverMedia {
ConcurrentJobQueue.shared.addJob(job: RecoverMediaJob())
}
WorkManager.general.wakeUpPersistedWorks(with: [
DeleteMessageAttachmentWork.self,
DeleteConversationAttachmentWork.self
])
initializeFTSIfNeeded()
refreshExternalSchemesIfNeeded()
}
Expand Down Expand Up @@ -739,9 +743,7 @@ extension HomeViewController {
self.conversations.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .fade)
self.tableView.endUpdates()
DispatchQueue.global().async {
ConversationDAO.shared.deleteChat(conversationId: conversationId)
}
ConversationCleaner.clean(conversationId: conversationId, intent: .delete)
}))
present(alert, animated: true, completion: nil)
}
Expand All @@ -763,9 +765,7 @@ extension HomeViewController {
self.conversations[indexPath.row].unseenMessageCount = 0
self.tableView.reloadRows(at: [indexPath], with: .automatic)
self.tableView.endUpdates()
DispatchQueue.global().async {
ConversationDAO.shared.clearChat(conversationId: conversationId)
}
ConversationCleaner.clean(conversationId: conversationId, intent: .clear)
}))
present(alert, animated: true, completion: nil)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ public final class ConversationDAO: UserDatabaseDAO {

public static let shared = ConversationDAO()

public static let willClearConversationNotification = Notification.Name("one.mixin.service.ConversationDAO.willClearConversation")
public static let conversationIdUserInfoKey = "cid"

private static let sqlQueryColumns = """
SELECT c.conversation_id as conversationId, c.owner_id as ownerId, c.icon_url as iconUrl,
c.announcement as announcement, c.category as category, c.name as name, c.status as status,
Expand Down Expand Up @@ -231,35 +228,6 @@ public final class ConversationDAO: UserDatabaseDAO {
}
}

public func clearChat(conversationId: String) {
let mediaUrls = MessageDAO.shared.getMediaUrls(conversationId: conversationId, categories: MessageCategory.allMediaCategories)
db.write { db in
let deletedTranscriptIds = try deleteTranscriptChildrenReferenced(by: conversationId, from: db)
NotificationCenter.default.post(onMainThread: Self.willClearConversationNotification,
object: self,
userInfo: [Self.conversationIdUserInfoKey: conversationId])
try Message
.filter(Message.column(of: .conversationId) == conversationId)
.deleteAll(db)
try MessageMention
.filter(MessageMention.column(of: .conversationId) == conversationId)
.deleteAll(db)
try Conversation
.filter(Conversation.column(of: .conversationId) == conversationId)
.updateAll(db, [Conversation.column(of: .unseenMessageCount).set(to: 0)])
try deleteFTSContent(with: conversationId, from: db)
try PinMessageDAO.shared.deleteAll(conversationId: conversationId, from: db)
db.afterNextTransactionCommit { (_) in
let job = AttachmentCleanUpJob(conversationId: conversationId,
mediaUrls: mediaUrls,
transcriptIds: deletedTranscriptIds)
ConcurrentJobQueue.shared.addJob(job: job)
let change = ConversationChange(conversationId: conversationId, action: .reload)
NotificationCenter.default.post(onMainThread: conversationDidChangeNotification, object: change)
}
}
}

public func getConversation(conversationId: String) -> ConversationItem? {
guard !conversationId.isEmpty else {
return nil
Expand Down Expand Up @@ -595,7 +563,7 @@ public final class ConversationDAO: UserDatabaseDAO {

extension ConversationDAO {

private func deleteFTSContent(with conversationId: String, from db: GRDB.Database) throws {
public func deleteFTSContent(with conversationId: String, from db: GRDB.Database) throws {
let sql = "DELETE FROM \(Message.ftsTableName) WHERE conversation_id MATCH ?"
try db.execute(sql: sql, arguments: [uuidTokenString(uuidString: conversationId)])
}
Expand Down
Loading