From 30c8ea29b2a4ab619641c697c494114a69bc34ea Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 10 Feb 2022 16:27:32 +0100 Subject: [PATCH] fix bug where the wrong left panel tile is removed when accepting invite because when comparing a tile to itself it wasn't returned 0 --- .../session/leftpanel/BaseTileViewModel.js | 2 +- .../session/leftpanel/InviteTileViewModel.js | 20 +++++++++++-- .../RoomBeingCreatedTileViewModel.js | 30 ++++++++++++++++--- .../session/leftpanel/RoomTileViewModel.js | 3 ++ src/domain/session/leftpanel/common.js | 23 ++++++++++++++ 5 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 src/domain/session/leftpanel/common.js diff --git a/src/domain/session/leftpanel/BaseTileViewModel.js b/src/domain/session/leftpanel/BaseTileViewModel.js index 95e91458..b360b1d4 100644 --- a/src/domain/session/leftpanel/BaseTileViewModel.js +++ b/src/domain/session/leftpanel/BaseTileViewModel.js @@ -18,7 +18,7 @@ limitations under the License. import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js"; import {ViewModel} from "../../ViewModel.js"; -const KIND_ORDER = ["invite", "room"]; +const KIND_ORDER = ["roomBeingCreated", "invite", "room"]; export class BaseTileViewModel extends ViewModel { constructor(options) { diff --git a/src/domain/session/leftpanel/InviteTileViewModel.js b/src/domain/session/leftpanel/InviteTileViewModel.js index bdc0e193..cdd955b1 100644 --- a/src/domain/session/leftpanel/InviteTileViewModel.js +++ b/src/domain/session/leftpanel/InviteTileViewModel.js @@ -1,5 +1,4 @@ /* -Copyright 2020 Bruno Windels Copyright 2020, 2021 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +15,7 @@ limitations under the License. */ import {BaseTileViewModel} from "./BaseTileViewModel.js"; +import {comparePrimitive} from "./common"; export class InviteTileViewModel extends BaseTileViewModel { constructor(options) { @@ -34,6 +34,9 @@ export class InviteTileViewModel extends BaseTileViewModel { get badgeCount() { return this.i18n`!`; } get _avatarSource() { return this._invite; } + /** very important that sorting order is stable and that comparing + * to itself always returns 0, otherwise SortedMapList will + * remove the wrong children, etc ... */ compare(other) { const parentComparison = super.compare(other); if (parentComparison !== 0) { @@ -43,6 +46,19 @@ export class InviteTileViewModel extends BaseTileViewModel { if (timeDiff !== 0) { return timeDiff; } - return this._invite.id < other._invite.id ? -1 : 1; + return comparePrimitive(this._invite.id, other._invite.id); + } +} + +export function tests() { + return { + "test compare with timestamp": assert => { + const urlCreator = {openRoomActionUrl() { return "";}} + const vm1 = new InviteTileViewModel({invite: {timestamp: 500, id: "1"}, urlCreator}); + const vm2 = new InviteTileViewModel({invite: {timestamp: 250, id: "2"}, urlCreator}); + assert(vm1.compare(vm2) < 0); + assert(vm2.compare(vm1) > 0); + assert.equal(vm1.compare(vm1), 0); + }, } } diff --git a/src/domain/session/leftpanel/RoomBeingCreatedTileViewModel.js b/src/domain/session/leftpanel/RoomBeingCreatedTileViewModel.js index e6fc4cee..81785bd9 100644 --- a/src/domain/session/leftpanel/RoomBeingCreatedTileViewModel.js +++ b/src/domain/session/leftpanel/RoomBeingCreatedTileViewModel.js @@ -16,6 +16,7 @@ limitations under the License. */ import {BaseTileViewModel} from "./BaseTileViewModel.js"; +import {comparePrimitive} from "./common"; export class RoomBeingCreatedTileViewModel extends BaseTileViewModel { constructor(options) { @@ -33,12 +34,20 @@ export class RoomBeingCreatedTileViewModel extends BaseTileViewModel { get name() { return this._roomBeingCreated.name; } get _avatarSource() { return this._roomBeingCreated; } + /** very important that sorting order is stable and that comparing + * to itself always returns 0, otherwise SortedMapList will + * remove the wrong children, etc ... */ compare(other) { - const parentComparison = super.compare(other); - if (parentComparison !== 0) { - return parentComparison; + const parentCmp = super.compare(other); + if (parentCmp !== 0) { + return parentCmp; + } + const nameCmp = comparePrimitive(this.name, other.name); + if (nameCmp === 0) { + return comparePrimitive(this._roomBeingCreated.id, other._roomBeingCreated.id); + } else { + return nameCmp; } - return other._roomBeingCreated.name.localeCompare(this._roomBeingCreated.name); } avatarUrl(size) { @@ -46,3 +55,16 @@ export class RoomBeingCreatedTileViewModel extends BaseTileViewModel { return this._roomBeingCreated.avatarBlobUrl ?? super.avatarUrl(size); } } + +export function tests() { + return { + "test compare with names": assert => { + const urlCreator = {openRoomActionUrl() { return "";}} + const vm1 = new RoomBeingCreatedTileViewModel({roomBeingCreated: {name: "A", id: "1"}, urlCreator}); + const vm2 = new RoomBeingCreatedTileViewModel({roomBeingCreated: {name: "B", id: "2"}, urlCreator}); + assert(vm1.compare(vm2) < 0); + assert(vm2.compare(vm1) > 0); + assert.equal(vm1.compare(vm1), 0); + }, + } +} diff --git a/src/domain/session/leftpanel/RoomTileViewModel.js b/src/domain/session/leftpanel/RoomTileViewModel.js index eebea618..8c38bb3e 100644 --- a/src/domain/session/leftpanel/RoomTileViewModel.js +++ b/src/domain/session/leftpanel/RoomTileViewModel.js @@ -33,6 +33,9 @@ export class RoomTileViewModel extends BaseTileViewModel { return this._url; } + /** very important that sorting order is stable and that comparing + * to itself always returns 0, otherwise SortedMapList will + * remove the wrong children, etc ... */ compare(other) { const parentComparison = super.compare(other); if (parentComparison !== 0) { diff --git a/src/domain/session/leftpanel/common.js b/src/domain/session/leftpanel/common.js new file mode 100644 index 00000000..3af95eba --- /dev/null +++ b/src/domain/session/leftpanel/common.js @@ -0,0 +1,23 @@ +/* +Copyright 2020, 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export function comparePrimitive(a, b) { + if (a === b) { + return 0; + } else { + return a < b ? -1 : 1; + } +}