Skip to content

Commit

Permalink
Fixed issue with chat list not being sorted correctly #beagleim-372
Browse files Browse the repository at this point in the history
  • Loading branch information
hantu85 committed Jul 2, 2021
1 parent 00a81e6 commit 51ee9f5
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 57 deletions.
4 changes: 4 additions & 0 deletions BeagleIM.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
FE75CD6C2546FC820064A733 /* HTTPFileUploadHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE75CD6B2546FC820064A733 /* HTTPFileUploadHelper.swift */; };
FE75CD702549E9BE0064A733 /* SharingTaskManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE75CD6F2549E9BE0064A733 /* SharingTaskManager.swift */; };
FE7F876C2343D99300254AF2 /* CustomScroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE7F876B2343D99300254AF2 /* CustomScroller.swift */; };
FE82A72D268E5E550049C844 /* Collection+calculateChanges.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE82A72C268E5E550049C844 /* Collection+calculateChanges.swift */; };
FE834882268A1C08000C171A /* DropDownButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE834881268A1C08000C171A /* DropDownButton.swift */; };
FE83E363217A3809001DEF09 /* JingleManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE83E362217A3809001DEF09 /* JingleManager.swift */; };
FE83E365217B0F89001DEF09 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FE83E364217B0F89001DEF09 /* AVFoundation.framework */; };
Expand Down Expand Up @@ -389,6 +390,7 @@
FE75CD6B2546FC820064A733 /* HTTPFileUploadHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPFileUploadHelper.swift; sourceTree = "<group>"; };
FE75CD6F2549E9BE0064A733 /* SharingTaskManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingTaskManager.swift; sourceTree = "<group>"; };
FE7F876B2343D99300254AF2 /* CustomScroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomScroller.swift; sourceTree = "<group>"; };
FE82A72C268E5E550049C844 /* Collection+calculateChanges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+calculateChanges.swift"; sourceTree = "<group>"; };
FE834881268A1C08000C171A /* DropDownButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDownButton.swift; sourceTree = "<group>"; };
FE83E362217A3809001DEF09 /* JingleManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JingleManager.swift; sourceTree = "<group>"; };
FE83E364217B0F89001DEF09 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -682,6 +684,7 @@
FE1A3481258923EE0058B86A /* Array+IndexChanges.swift */,
FE1A34DB2592144A0058B86A /* PresenceStore.swift */,
FE67E1C225A8E120005D034C /* NotificationsManager.swift */,
FE82A72C268E5E550049C844 /* Collection+calculateChanges.swift */,
);
path = utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -1271,6 +1274,7 @@
FEA2F53722E5F6A2009F2E88 /* AdvancedSettingsController.swift in Sources */,
FE8F7CEC2562F8BD0076C13E /* ConversationKey.swift in Sources */,
FED7AEC921418FA9001E164B /* DBVCardStore.swift in Sources */,
FE82A72D268E5E550049C844 /* Collection+calculateChanges.swift in Sources */,
FE222D032561879700C186A9 /* DBChatStore+RoomStore.swift in Sources */,
FEA8941F2156625E004C3B51 /* ConfigureRoomViewController.swift in Sources */,
FEA2997025B9EDC50021865E /* SuggestionsWindowController.swift in Sources */,
Expand Down
1 change: 1 addition & 0 deletions BeagleIM/MIX.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ AAAAAAEGA
<connections>
<outlet property="actionsButton" destination="d4m-nZ-ark" id="w2n-i1-rLU"/>
<outlet property="actionsButtonLeadConstraint" destination="SYm-bT-Q8K" id="pEp-bN-sPD"/>
<outlet property="bottomView" destination="MAp-aV-bfL" id="kSJ-JA-ifD"/>
<outlet property="channelAvatarView" destination="yp1-x3-zO9" id="5Et-7z-g3x"/>
<outlet property="channelDescriptionLabel" destination="Ri7-Rr-BHY" id="vzO-ef-sMa"/>
<outlet property="channelJidLabel" destination="Uwz-yJ-FRm" id="Ie4-Fx-0D3"/>
Expand Down
39 changes: 12 additions & 27 deletions BeagleIM/chatslist/groups/ChatsListGroupAbstractChat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,40 +66,25 @@ class ChatsListGroupAbstractChat: ChatsListGroupProtocol {
let newItems = items.filter(self.isAccepted(chat:)).map({ conversation in ConversationItem(chat: conversation, timestamp: conversation.timestamp) }).sorted(by: { (c1,c2) in c1.timestamp > c2.timestamp });
let oldItems = self.items;

let diffs = newItems.difference(from: oldItems).inferringMoves();
var removed: [Int] = [];
var inserted: [Int] = [];
var moved: [(Int,Int)] = [];
for action in diffs {
switch action {
case .remove(let offset, _, let to):
if let idx = to {
moved.append((offset, idx));
} else {
removed.append(offset);
}
case .insert(let offset, _, let from):
if from == nil {
inserted.append(offset);
}
}
}
let changes: [CollectionChange] = newItems.calculateChanges(from: oldItems);

guard (!removed.isEmpty) || (!moved.isEmpty) || (!inserted.isEmpty) else {
guard !changes.isEmpty else {
return;
}

DispatchQueue.main.sync {
self.items = newItems;
self.delegate?.beginUpdates();
if !removed.isEmpty {
self.delegate?.itemsRemoved(at: IndexSet(removed), inParent: self);
}
for (from,to) in moved {
self.delegate?.itemMoved(from: from, fromParent: self, to: to, toParent: self);
}
if !inserted.isEmpty {
self.delegate?.itemsInserted(at: IndexSet(inserted), inParent: self);

for change in changes {
switch change {
case .insert(let idx):
self.delegate?.itemsInserted(at: IndexSet(integer: idx), inParent: self);
case .remove(let idx):
self.delegate?.itemsRemoved(at: IndexSet(integer: idx), inParent: self);
case .move(let from, let to):
self.delegate?.itemMoved(from: from, fromParent: self, to: to, toParent: self);
}
}
self.delegate?.endUpdates();
}
Expand Down
50 changes: 20 additions & 30 deletions BeagleIM/chatslist/groups/InvitationGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,42 +63,32 @@ class InvitationGroup: ChatsListGroupProtocol {
let newItems = items.sorted(by: { (i1, i2) -> Bool in i1.order > i2.order });
let oldItems = self.items;

let diffs = newItems.difference(from: oldItems).inferringMoves();
var removed: [Int] = [];
var inserted: [Int] = [];
var moved: [(Int,Int)] = [];
for action in diffs {
switch action {
case .remove(let offset, _, let to):
if let idx = to {
moved.append((offset, idx));
} else {
removed.append(offset);
}
case .insert(let offset, _, let from):
if from == nil {
inserted.append(offset);
}
}
let changes: [CollectionChange] = newItems.calculateChanges(from: oldItems);

guard !changes.isEmpty else {
return;
}

self.items = newItems;
self.delegate?.beginUpdates();
if !removed.isEmpty {
self.delegate?.itemsRemoved(at: IndexSet(removed), inParent: self);
if newItems.isEmpty && !oldItems.isEmpty {
self.delegate?.invitationGroup(show: false);

self.items = newItems;
for change in changes {
switch change {
case .insert(let idx):
self.delegate?.itemsInserted(at: IndexSet(integer: idx), inParent: self);
case .remove(let idx):
self.delegate?.itemsRemoved(at: IndexSet(integer: idx), inParent: self);
case .move(let from, let to):
self.delegate?.itemMoved(from: from, fromParent: self, to: to, toParent: self);
}
}
for (from,to) in moved {
self.delegate?.itemMoved(from: from, fromParent: self, to: to, toParent: self);

if oldItems.isEmpty && !newItems.isEmpty {
self.delegate?.invitationGroup(show: true);
}
if !inserted.isEmpty {
if oldItems.isEmpty && !newItems.isEmpty {
self.delegate?.invitationGroup(show: true);
} else {
self.delegate?.itemsInserted(at: IndexSet(inserted), inParent: self);
}

if newItems.isEmpty && !oldItems.isEmpty {
self.delegate?.invitationGroup(show: false);
}
self.delegate?.endUpdates();
}
Expand Down
58 changes: 58 additions & 0 deletions BeagleIM/utils/Collection+calculateChanges.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//
// Collection+calculateChanges.swift
//
// BeagleIM
// Copyright (C) 2021 "Tigase, Inc." <office@tigase.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. Look for COPYING file in the top folder.
// If not, see https://www.gnu.org/licenses/.
//
import Foundation

extension BidirectionalCollection where Element: Hashable {

func calculateChanges<C>(from other: C) -> [CollectionChange] where C: BidirectionalCollection, Element == C.Element {
let diffs = self.difference(from: other).inferringMoves();

var changes: [CollectionChange] = []
var movedOffsets: [Element:Int] = [:];

for action in diffs {
print("action:", action)
switch action {
case .remove(let offset, let el, let to):
if to != nil {
movedOffsets[el] = offset;
} else {
changes.append(.remove(offset + movedOffsets.values.filter({ $0 < offset}).count))
}
case .insert(let offset, let el, let from):
if let idx = from {
movedOffsets.removeValue(forKey: el);
changes.append(.move(idx + movedOffsets.values.filter({ $0 < idx}).count, offset + movedOffsets.values.filter({ $0 < offset}).count));
} else {
changes.append(.insert(offset + movedOffsets.values.filter({ $0 < offset}).count));
}
}
}
return changes;
}

}

enum CollectionChange {
case remove(Int)
case insert(Int)
case move(Int,Int)
}

0 comments on commit 51ee9f5

Please sign in to comment.