Skip to content

Commit c5b49c3

Browse files
authored
Merge pull request #751 from Adamant-im/trello.com/c/hG3JTo2a
[trello.com/c/hG3JTo2a] Updating chats drops current chat highlighting on macOS
2 parents 711fe8b + 48596c6 commit c5b49c3

File tree

5 files changed

+82
-76
lines changed

5 files changed

+82
-76
lines changed

Adamant/Modules/Chat/View/ChatViewController.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,7 @@ final class ChatViewController: MessagesViewController {
190190

191191
override func viewDidDisappear(_ animated: Bool) {
192192
super.viewDidDisappear(animated)
193-
viewModel.preserveFiles()
194193
viewModel.preserveMessage(inputBar.text)
195-
viewModel.preserveReplayMessage()
196194
viewModel.saveChatOffset(
197195
isScrollPositionNearlyTheBottom
198196
? nil

Adamant/Modules/Chat/ViewModel/ChatPreservationProtocol.swift

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,10 @@ import CommonKit
1010

1111
protocol ChatPreservationProtocol: AnyObject, Sendable {
1212
var updateNotifier: ObservableSender<Void> { get }
13-
func preserveMessage(_ message: String, forAddress address: String)
14-
func getPreservedMessageFor(address: String, thenRemoveIt: Bool) -> String?
15-
func setReplyMessage(_ message: MessageModel?, forAddress address: String)
16-
func getReplyMessage(address: String, thenRemoveIt: Bool) -> MessageModel?
17-
func preserveFiles(_ files: [FileResult]?, forAddress address: String)
13+
func getPreservedMessageFor(address: String) -> String?
14+
func getReplyMessage(address: String) -> MessageModel?
15+
func preserveChatState(message: String?, replyMessage: MessageModel?, files: [FileResult]?, forAddress address: String)
1816
func getPreservedFiles(
19-
for address: String,
20-
thenRemoveIt: Bool
17+
for address: String
2118
) -> [FileResult]?
2219
}

Adamant/Modules/Chat/ViewModel/ChatViewModel.swift

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -246,20 +246,16 @@ final class ChatViewModel: NSObject {
246246

247247
if let partnerAddress = chatroom.partner?.address {
248248
chatPreservation.getPreservedMessageFor(
249-
address: partnerAddress,
250-
thenRemoveIt: true
249+
address: partnerAddress
251250
).map { inputText = $0 }
252251

253252
let cachedMessages = chatCacheService.getMessages(address: partnerAddress)
254253
messages = cachedMessages ?? []
255254
fullscreenLoading = cachedMessages == nil
256255

257-
replyMessage = chatPreservation.getReplyMessage(address: partnerAddress, thenRemoveIt: true)
256+
replyMessage = chatPreservation.getReplyMessage(address: partnerAddress)
258257

259-
filesPicked = chatPreservation.getPreservedFiles(
260-
for: partnerAddress,
261-
thenRemoveIt: true
262-
)
258+
filesPicked = chatPreservation.getPreservedFiles(for: partnerAddress)
263259
}
264260
if isNewChat && !(accountService.account?.isEnoughMoneyForTransaction ?? false) {
265261
dialog.send(.freeTokenAlert)
@@ -385,17 +381,7 @@ final class ChatViewModel: NSObject {
385381

386382
func preserveMessage(_ message: String) {
387383
guard let partnerAddress = chatroom?.partner?.address else { return }
388-
chatPreservation.preserveMessage(message, forAddress: partnerAddress)
389-
}
390-
391-
func preserveFiles() {
392-
guard let partnerAddress = chatroom?.partner?.address else { return }
393-
chatPreservation.preserveFiles(filesPicked, forAddress: partnerAddress)
394-
}
395-
396-
func preserveReplayMessage() {
397-
guard let partnerAddress = chatroom?.partner?.address else { return }
398-
chatPreservation.setReplyMessage(replyMessage, forAddress: partnerAddress)
384+
chatPreservation.preserveChatState(message: message, replyMessage: replyMessage, files: filesPicked, forAddress: partnerAddress)
399385
}
400386

401387
func blockChat() {

Adamant/Modules/ChatsList/ChatListViewController.swift

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ final class ChatListViewController: KeyboardObservingViewController {
7676
setBadgeValue(unreadController?.fetchedObjects?.count)
7777
}
7878
}
79+
private var chatDeselectedIndex: IndexPath?
7980

8081
let defaultAvatar = UIImage.asset(named: "avatar-chat-placeholder") ?? .init()
8182

@@ -197,8 +198,11 @@ final class ChatListViewController: KeyboardObservingViewController {
197198

198199
override func viewWillAppear(_ animated: Bool) {
199200
super.viewWillAppear(animated)
200-
if let indexPath = tableView.indexPathForSelectedRow {
201-
tableView.deselectRow(at: indexPath, animated: animated)
201+
202+
if UIDevice.current.userInterfaceIdiom == .phone {
203+
if let indexPath = tableView.indexPathForSelectedRow {
204+
tableView.deselectRow(at: indexPath, animated: animated)
205+
}
202206
}
203207
}
204208
override func viewDidLayoutSubviews() {
@@ -342,7 +346,10 @@ final class ChatListViewController: KeyboardObservingViewController {
342346
chatPreservation.updateNotifier
343347
.receive(on: DispatchQueue.main)
344348
.sink { [weak self] in
345-
self?.tableView.reloadData()
349+
guard let deselectedIndex = self?.chatDeselectedIndex,
350+
let cell = self?.tableView.cellForRow(at: deselectedIndex) as? ChatTableViewCell,
351+
let chatroom = self?.chatsController?.fetchedObjects?[safe: deselectedIndex.row] else { return }
352+
self?.configureCell(cell, for: chatroom)
346353
}
347354
.store(in: &subscriptions)
348355
}
@@ -357,7 +364,7 @@ final class ChatListViewController: KeyboardObservingViewController {
357364

358365
private func updateUITitles() {
359366
updatingIndicatorView.updateTitle(title: String.adamant.chatList.title)
360-
tableView.reloadData()
367+
tableView.reloadDataPreservingSelection()
361368
searchController?.searchBar.placeholder = String.adamant.chatList.searchPlaceholder
362369
}
363370

@@ -408,7 +415,7 @@ final class ChatListViewController: KeyboardObservingViewController {
408415
areMessagesLoaded = true
409416
performOnMessagesLoadedActions()
410417
setIsBusy(!synced)
411-
tableView.reloadData()
418+
tableView.reloadDataPreservingSelection()
412419
}
413420

414421
// MARK: IB Actions
@@ -479,7 +486,7 @@ final class ChatListViewController: KeyboardObservingViewController {
479486

480487
switch result {
481488
case .success:
482-
tableView.reloadData()
489+
tableView.reloadDataPreservingSelection()
483490
case .failure(let error):
484491
dialogService.showRichError(error: error)
485492
}
@@ -564,6 +571,10 @@ extension ChatListViewController: UITableViewDelegate, UITableViewDataSource {
564571
return UIView()
565572
}
566573

574+
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
575+
chatDeselectedIndex = indexPath
576+
}
577+
567578
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
568579
if isBusy,
569580
indexPath.row == lastSystemChatPositionRow,
@@ -719,15 +730,15 @@ extension ChatListViewController {
719730

720731
private func insertReloadRow() {
721732
lastSystemChatPositionRow = getBottomSystemChatIndex()
722-
tableView.reloadData()
733+
tableView.reloadDataPreservingSelection()
723734
}
724735

725736
@MainActor
726737
private func loadNewChats(offset: Int) {
727738
loadNewChatTask = Task {
728739
await chatsProvider.getChatRooms(offset: offset)
729740
isBusy = false
730-
tableView.reloadData()
741+
tableView.reloadDataPreservingSelection()
731742
}
732743
}
733744
}
@@ -1065,14 +1076,14 @@ extension ChatListViewController {
10651076
private func shortDescription(for address: String) -> NSAttributedString? {
10661077
var descriptionParts: [NSAttributedString] = []
10671078

1068-
if chatPreservation.getReplyMessage(address: address, thenRemoveIt: false) != nil {
1079+
if chatPreservation.getReplyMessage(address: address) != nil {
10691080
let replyImageAttachment = NSTextAttachment()
10701081
replyImageAttachment.image = UIImage(systemName: "arrowshape.turn.up.left")?.withTintColor(.adamant.primary)
10711082
replyImageAttachment.bounds = CGRect(x: .zero, y: -3, width: 23, height: 20)
10721083

10731084
descriptionParts.append(NSAttributedString(attachment: replyImageAttachment))
10741085
}
1075-
if let files = chatPreservation.getPreservedFiles(for: address, thenRemoveIt: false), !files.isEmpty {
1086+
if let files = chatPreservation.getPreservedFiles(for: address), !files.isEmpty {
10761087
let mediaCount = files.count(where: { $0.type.isMedia })
10771088
let otherCount = files.count(where: { !$0.type.isMedia })
10781089

@@ -1093,7 +1104,7 @@ extension ChatListViewController {
10931104
}
10941105
}
10951106

1096-
if let preservedMessage = chatPreservation.getPreservedMessageFor(address: address, thenRemoveIt: false) {
1107+
if let preservedMessage = chatPreservation.getPreservedMessageFor(address: address) {
10971108
let processedMessage = MessageProcessHelper.process(preservedMessage)
10981109
descriptionParts.append(NSAttributedString(string: processedMessage))
10991110
}
@@ -1595,5 +1606,13 @@ private extension UITableView {
15951606
reloadRows(at: indexPaths, with: .none)
15961607
selectRow(at: selectedRowIndexPath, animated: false, scrollPosition: .none)
15971608
}
1609+
1610+
func reloadDataPreservingSelection() {
1611+
let selectedRow = indexPathForSelectedRow
1612+
reloadData()
1613+
if let selectedRow = selectedRow {
1614+
selectRow(at: selectedRow, animated: false, scrollPosition: .none)
1615+
}
1616+
}
15981617
}
15991618

Adamant/ServiceProtocols/ChatPreservation.swift

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -32,63 +32,69 @@ final class ChatPreservation: ChatPreservationProtocol, @unchecked Sendable {
3232
preservedMessages = [:]
3333
preservedReplayMessage = [:]
3434
preservedFiles = [:]
35+
3536
updateNotifier.send()
3637
}
3738

38-
func preserveMessage(_ message: String, forAddress address: String) {
39-
preservedMessages[address] = message
40-
updateNotifier.send()
39+
func preserveChatState(
40+
message: String?,
41+
replyMessage: MessageModel?,
42+
files: [FileResult]?,
43+
forAddress address: String
44+
) {
45+
var shouldNotify = false
46+
47+
if let message = message, !message.isEmpty {
48+
preservedMessages[address] = message
49+
shouldNotify = true
50+
} else if preservedMessages[address] != nil {
51+
preservedMessages.removeValue(forKey: address)
52+
shouldNotify = true
53+
}
54+
55+
if let replyMessage = replyMessage {
56+
preservedReplayMessage[address] = replyMessage
57+
shouldNotify = true
58+
} else if preservedReplayMessage[address] != nil {
59+
preservedReplayMessage.removeValue(forKey: address)
60+
shouldNotify = true
61+
}
62+
63+
if let files = files {
64+
preservedFiles[address] = files
65+
shouldNotify = true
66+
67+
} else if preservedFiles[address] != nil {
68+
preservedFiles.removeValue(forKey: address)
69+
shouldNotify = true
70+
}
71+
72+
if shouldNotify {
73+
updateNotifier.send()
74+
}
4175
}
4276

43-
func getPreservedMessageFor(address: String, thenRemoveIt: Bool) -> String? {
77+
func getPreservedMessageFor(address: String) -> String? {
4478
guard let message = preservedMessages[address] else {
4579
return nil
4680
}
47-
48-
if thenRemoveIt {
49-
preservedMessages.removeValue(forKey: address)
50-
updateNotifier.send()
51-
}
52-
81+
5382
return message
5483
}
5584

56-
func setReplyMessage(_ message: MessageModel?, forAddress address: String) {
57-
preservedReplayMessage[address] = message
58-
updateNotifier.send()
59-
}
60-
61-
func getReplyMessage(address: String, thenRemoveIt: Bool) -> MessageModel? {
62-
guard let replayMessage = preservedReplayMessage[address] else {
85+
func getReplyMessage(address: String) -> MessageModel? {
86+
guard let replyMessage = preservedReplayMessage[address] else {
6387
return nil
6488
}
6589

66-
if thenRemoveIt {
67-
preservedMessages.removeValue(forKey: address)
68-
updateNotifier.send()
69-
}
70-
71-
return replayMessage
90+
return replyMessage
7291
}
7392

74-
func preserveFiles(_ files: [FileResult]?, forAddress address: String) {
75-
preservedFiles[address] = files
76-
updateNotifier.send()
77-
}
78-
79-
func getPreservedFiles(
80-
for address: String,
81-
thenRemoveIt: Bool
82-
) -> [FileResult]? {
93+
func getPreservedFiles(for address: String) -> [FileResult]? {
8394
guard let files = preservedFiles[address] else {
8495
return nil
8596
}
86-
87-
if thenRemoveIt {
88-
preservedFiles.removeValue(forKey: address)
89-
updateNotifier.send()
90-
}
91-
97+
9298
return files
9399
}
94100
}

0 commit comments

Comments
 (0)