Skip to content

Commit 4ae04fc

Browse files
committed
adding normalised room display name field and making use of it when filtering rooms by name
- fixes non latin-1 character set room names from being ignored when searching with inexact casing
1 parent d5ed959 commit 4ae04fc

File tree

8 files changed

+51
-9
lines changed

8 files changed

+51
-9
lines changed

matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/query/QueryStringValue.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,6 @@ sealed interface QueryStringValue {
3939
INSENSITIVE,
4040
NORMALIZED
4141
}
42+
43+
fun isNormalized() = this is ContentQueryStringValue && case == Case.NORMALIZED
4244
}

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,17 @@ import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
4545
import org.matrix.android.sdk.internal.database.model.presence.UserPresenceEntityFields
4646
import org.matrix.android.sdk.internal.di.MoshiProvider
4747
import org.matrix.android.sdk.internal.query.process
48+
import org.matrix.android.sdk.internal.util.Normalizer
4849
import timber.log.Timber
50+
import javax.inject.Inject
4951

50-
internal object RealmSessionStoreMigration : RealmMigration {
52+
internal class RealmSessionStoreMigration @Inject constructor(
53+
private val normalizer: Normalizer
54+
) : RealmMigration {
5155

52-
const val SESSION_STORE_SCHEMA_VERSION = 18L
56+
companion object {
57+
const val SESSION_STORE_SCHEMA_VERSION = 19L
58+
}
5359

5460
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
5561
Timber.v("Migrating Realm Session from $oldVersion to $newVersion")
@@ -72,6 +78,7 @@ internal object RealmSessionStoreMigration : RealmMigration {
7278
if (oldVersion <= 15) migrateTo16(realm)
7379
if (oldVersion <= 16) migrateTo17(realm)
7480
if (oldVersion <= 17) migrateTo18(realm)
81+
if (oldVersion <= 18) migrateTo19(realm)
7582
}
7683

7784
private fun migrateTo1(realm: DynamicRealm) {
@@ -364,4 +371,16 @@ internal object RealmSessionStoreMigration : RealmMigration {
364371
realm.schema.get("RoomMemberSummaryEntity")
365372
?.addRealmObjectField(RoomMemberSummaryEntityFields.USER_PRESENCE_ENTITY.`$`, userPresenceEntity)
366373
}
374+
375+
private fun migrateTo19(realm: DynamicRealm) {
376+
Timber.d("Step 18 -> 19")
377+
realm.schema.get("RoomSummaryEntity")
378+
?.addField(RoomSummaryEntityFields.NORMALIZED_DISPLAY_NAME, String::class.java)
379+
?.transform {
380+
it.getString(RoomSummaryEntityFields.DISPLAY_NAME)?.let { displayName ->
381+
val normalised = normalizer.normalize(displayName)
382+
it.set(RoomSummaryEntityFields.NORMALIZED_DISPLAY_NAME, normalised)
383+
}
384+
}
385+
}
367386
}

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/SessionRealmConfigurationFactory.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ private const val REALM_NAME = "disk_store.realm"
4040
*/
4141
internal class SessionRealmConfigurationFactory @Inject constructor(
4242
private val realmKeysUtils: RealmKeysUtils,
43+
private val realmSessionStoreMigration: RealmSessionStoreMigration,
4344
@SessionFilesDirectory val directory: File,
4445
@SessionId val sessionId: String,
4546
@UserMd5 val userMd5: String,
@@ -71,7 +72,7 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
7172
.allowWritesOnUiThread(true)
7273
.modules(SessionRealmModule())
7374
.schemaVersion(RealmSessionStoreMigration.SESSION_STORE_SCHEMA_VERSION)
74-
.migration(RealmSessionStoreMigration)
75+
.migration(realmSessionStoreMigration)
7576
.build()
7677

7778
// Try creating a realm instance and if it succeeds we can clear the flag

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ internal open class RoomSummaryEntity(
4040
set(value) {
4141
if (value != field) field = value
4242
}
43+
44+
/**
45+
* Workaround for Realm only supporting Latin-1 character sets when sorting
46+
* or filtering by case
47+
* See https://github.com/realm/realm-core/issues/777
48+
*/
49+
var normalizedDisplayName: String? = ""
50+
set(value) {
51+
if (value != field) field = value
52+
}
53+
4354
var avatarUrl: String? = ""
4455
set(value) {
4556
if (value != field) field = value
@@ -284,5 +295,6 @@ internal open class RoomSummaryEntity(
284295
roomEncryptionTrustLevelStr = value?.name
285296
}
286297
}
298+
287299
companion object
288300
}

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,11 @@ internal class RoomSummaryDataSource @Inject constructor(
245245
val query = with(queryStringValueProcessor) {
246246
val query = RoomSummaryEntity.where(realm)
247247
query.process(RoomSummaryEntityFields.ROOM_ID, queryParams.roomId)
248-
query.process(RoomSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
248+
if (queryParams.displayName.isNormalized()) {
249+
query.process(RoomSummaryEntityFields.NORMALIZED_DISPLAY_NAME, queryParams.displayName)
250+
} else {
251+
query.process(RoomSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
252+
}
249253
query.process(RoomSummaryEntityFields.CANONICAL_ALIAS, queryParams.canonicalAlias)
250254
query.process(RoomSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
251255
query.equalTo(RoomSummaryEntityFields.IS_HIDDEN_FROM_USER, false)

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ import org.matrix.android.sdk.internal.session.room.accountdata.RoomAccountDataD
6565
import org.matrix.android.sdk.internal.session.room.membership.RoomDisplayNameResolver
6666
import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper
6767
import org.matrix.android.sdk.internal.session.room.relationship.RoomChildRelationInfo
68+
import org.matrix.android.sdk.internal.util.Normalizer
6869
import timber.log.Timber
6970
import javax.inject.Inject
7071
import kotlin.system.measureTimeMillis
@@ -75,7 +76,8 @@ internal class RoomSummaryUpdater @Inject constructor(
7576
private val roomAvatarResolver: RoomAvatarResolver,
7677
private val eventDecryptor: EventDecryptor,
7778
private val crossSigningService: DefaultCrossSigningService,
78-
private val roomAccountDataDataSource: RoomAccountDataDataSource) {
79+
private val roomAccountDataDataSource: RoomAccountDataDataSource,
80+
private val normalizer: Normalizer) {
7981

8082
fun update(realm: Realm,
8183
roomId: String,
@@ -136,7 +138,9 @@ internal class RoomSummaryUpdater @Inject constructor(
136138
// avoid this call if we are sure there are unread events
137139
!isEventRead(realm.configuration, userId, roomId, latestPreviewableEvent?.eventId)
138140

139-
roomSummaryEntity.displayName = roomDisplayNameResolver.resolve(realm, roomId)
141+
val roomDisplayName = roomDisplayNameResolver.resolve(realm, roomId)
142+
roomSummaryEntity.displayName = roomDisplayName
143+
roomSummaryEntity.normalizedDisplayName = normalizer.normalize(roomDisplayName)
140144
roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(realm, roomId)
141145
roomSummaryEntity.name = ContentMapper.map(lastNameEvent?.content).toModel<RoomNameContent>()?.name
142146
roomSummaryEntity.topic = ContentMapper.map(lastTopicEvent?.content).toModel<RoomTopicContent>()?.topic

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Normalizer.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/*
2-
* Copyright (c) 2021 New Vector Ltd
2+
* Copyright 2021 The Matrix.org Foundation C.I.C.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
66
* You may obtain a copy of the License at
77
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
8+
* http://www.apache.org/licenses/LICENSE-2.0
99
*
1010
* Unless required by applicable law or agreed to in writing, software
1111
* distributed under the License is distributed on an "AS IS" BASIS,

vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ class RoomListViewModel @AssistedInject constructor(
191191
}
192192
updatableQuery?.updateQuery {
193193
it.copy(
194-
displayName = QueryStringValue.Contains(action.filter, QueryStringValue.Case.INSENSITIVE)
194+
displayName = QueryStringValue.Contains(action.filter, QueryStringValue.Case.NORMALIZED)
195195
)
196196
}
197197
}

0 commit comments

Comments
 (0)