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

Delight edit layout experiment #1515

Merged
merged 12 commits into from
Aug 2, 2022
Merged
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
6 changes: 6 additions & 0 deletions MatrixSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,8 @@
3A23A740256D322C00B9D00F /* MXAes.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A23A73D256D322C00B9D00F /* MXAes.m */; };
3A23A741256D322C00B9D00F /* MXAes.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A23A73E256D322C00B9D00F /* MXAes.h */; settings = {ATTRIBUTES = (Public, ); }; };
3A23A742256D322C00B9D00F /* MXAes.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A23A73E256D322C00B9D00F /* MXAes.h */; settings = {ATTRIBUTES = (Public, ); }; };
3A5787A528982D4600A0D8A8 /* MXBreadcrumbsRoomListDataFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A5787A428982D4600A0D8A8 /* MXBreadcrumbsRoomListDataFetcher.swift */; };
3A5787A628982D4600A0D8A8 /* MXBreadcrumbsRoomListDataFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A5787A428982D4600A0D8A8 /* MXBreadcrumbsRoomListDataFetcher.swift */; };
3A59A49D25A7A16F00DDA1FC /* MXOlmOutboundGroupSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A59A49B25A7A16E00DDA1FC /* MXOlmOutboundGroupSession.h */; settings = {ATTRIBUTES = (Public, ); }; };
3A59A49E25A7A16F00DDA1FC /* MXOlmOutboundGroupSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A59A49B25A7A16E00DDA1FC /* MXOlmOutboundGroupSession.h */; settings = {ATTRIBUTES = (Public, ); }; };
3A59A49F25A7A16F00DDA1FC /* MXOlmOutboundGroupSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A59A49C25A7A16F00DDA1FC /* MXOlmOutboundGroupSession.m */; };
Expand Down Expand Up @@ -2419,6 +2421,7 @@
3A108E6625826F52005EEBE9 /* MXKeyProviderUnitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXKeyProviderUnitTests.m; sourceTree = "<group>"; };
3A23A73D256D322C00B9D00F /* MXAes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXAes.m; sourceTree = "<group>"; };
3A23A73E256D322C00B9D00F /* MXAes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXAes.h; sourceTree = "<group>"; };
3A5787A428982D4600A0D8A8 /* MXBreadcrumbsRoomListDataFetcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MXBreadcrumbsRoomListDataFetcher.swift; sourceTree = "<group>"; };
3A59A49B25A7A16E00DDA1FC /* MXOlmOutboundGroupSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXOlmOutboundGroupSession.h; sourceTree = "<group>"; };
3A59A49C25A7A16F00DDA1FC /* MXOlmOutboundGroupSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXOlmOutboundGroupSession.m; sourceTree = "<group>"; };
3A59A52725A7B1B000DDA1FC /* MXOutboundSessionInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXOutboundSessionInfo.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4688,6 +4691,7 @@
EC1165A927107E330089FA56 /* MXSuggestedRoomListDataCache.swift */,
EC0B941D27186C3500B4D440 /* MXRoomListDataSortable.swift */,
EC0B942027186D4600B4D440 /* MXRoomListDataFilterable.swift */,
3A5787A428982D4600A0D8A8 /* MXBreadcrumbsRoomListDataFetcher.swift */,
);
path = Common;
sourceTree = "<group>";
Expand Down Expand Up @@ -6141,6 +6145,7 @@
32B76EA520FDE85100B095F6 /* MXRoomMembersCount.m in Sources */,
3AD4F231274B922D003F47FE /* MXRoomAliasAvailabilityChecker.swift in Sources */,
B1710B1F2613D01400A9B429 /* MXSpaceChildrenRequestParameters.swift in Sources */,
3A5787A528982D4600A0D8A8 /* MXBreadcrumbsRoomListDataFetcher.swift in Sources */,
32CEEF4B23B0A8170039BA98 /* MXCrossSigningTools.m in Sources */,
EC8A53A525B1BC77004E0802 /* MXCallInviteEventContent.m in Sources */,
323F877D25546170009E9E67 /* MXBaseProfiler.m in Sources */,
Expand Down Expand Up @@ -6709,6 +6714,7 @@
B16C56E3261D0A9D00604765 /* MXSpaceChildInfo.swift in Sources */,
3AD4F232274B922D003F47FE /* MXRoomAliasAvailabilityChecker.swift in Sources */,
B14EF1D52397E90400758AF0 /* MXEventAnnotation.m in Sources */,
3A5787A628982D4600A0D8A8 /* MXBreadcrumbsRoomListDataFetcher.swift in Sources */,
B14EF1D62397E90400758AF0 /* MXPusher.m in Sources */,
B14EF1D72397E90400758AF0 /* MXMediaLoader.m in Sources */,
32549AF823F2E2790002576B /* MXKeyVerificationReady.m in Sources */,
Expand Down
4 changes: 4 additions & 0 deletions MatrixSDK/Data/MXRoomSummary.m
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,10 @@ - (MXRoomSummaryDataTypes)calculateDataTypes
{
result |= MXRoomSummaryDataTypesConferenceUser;
}
if (self.hasAnyUnread)
{
result |= MXRoomSummaryDataTypesUnread;
}

return result;
}
Expand Down
3 changes: 2 additions & 1 deletion MatrixSDK/Data/MXRoomSummaryDataTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ typedef NS_OPTIONS(NSInteger, MXRoomSummaryDataTypes)
MXRoomSummaryDataTypesServerNotice = 1 << 4,
MXRoomSummaryDataTypesHidden = 1 << 5,
MXRoomSummaryDataTypesSpace = 1 << 6,
MXRoomSummaryDataTypesConferenceUser = 1 << 7
MXRoomSummaryDataTypesConferenceUser = 1 << 7,
MXRoomSummaryDataTypesUnread = 1 << 8
};

#endif /* MXRoomSummaryDataTypes_h */
149 changes: 149 additions & 0 deletions MatrixSDK/Data/RoomList/Common/MXBreadcrumbsRoomListDataFetcher.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
//
// Copyright 2022 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.
//

import Foundation

@objcMembers
internal class MXBreadcrumbsRoomListDataFetcher: NSObject, MXRoomListDataFetcher {
internal var fetchOptions: MXRoomListDataFetchOptions
private weak var session: MXSession?
private var recentsRooms: [String] = []

private var allRoomSummaries: [MXRoomSummaryProtocol] = []
private var sessionSyncObserver: Any?

private var recentRoomIds: [String] = []

private let multicastDelegate: MXMulticastDelegate<MXRoomListDataFetcherDelegate> = MXMulticastDelegate()

var data: MXRoomListData? {
didSet {
guard data != nil else {
// do not notify when stopped
return
}

notifyDataChange()
}
}

internal init(fetchOptions: MXRoomListDataFetchOptions,
session: MXSession?) {
self.fetchOptions = fetchOptions
self.session = session
super.init()
self.fetchOptions.fetcher = self
self.refresh()
self.addDataObservers()
}

// MARK: - Delegate

func addDelegate(_ delegate: MXRoomListDataFetcherDelegate) {
multicastDelegate.addDelegate(delegate)
}

func removeDelegate(_ delegate: MXRoomListDataFetcherDelegate) {
multicastDelegate.removeDelegate(delegate)
}

func removeAllDelegates() {
multicastDelegate.removeAllDelegates()
}

internal func notifyDataChange() {
multicastDelegate.invoke({ $0.fetcherDidChangeData(self, totalCountsChanged: true) })
}

func paginate() {
// Do nothing. We don't paginate breadcrumbs
}

func resetPagination() {
// Do nothing. We don't paginate breadcrumbs
}

// MARK: - Public

func refresh() {
guard let breadcrumbs = session?.accountData?.accountData(forEventType: kMXAccountDataTypeBreadcrumbs) as? [AnyHashable: [String]] else {
MXLog.warning("[MXBreadcrumbsRoomListDataFetcher] cannot retrieve breadcrumbs")
return
}

guard var recentRoomIds = breadcrumbs[kMXAccountDataTypeRecentRoomsKey] else {
MXLog.warning("[MXBreadcrumbsRoomListDataFetcher] cannot retrieve recent rooms")
return
}

if let query = fetchOptions.filterOptions.query?.lowercased(), !query.isEmpty {
recentRoomIds = recentRoomIds.filter({ roomId in
guard let summary = session?.roomSummary(withRoomId: roomId) else {
return false
}
return summary.displayname.lowercased().contains(query)
})
}

guard self.recentRoomIds != recentRoomIds else {
// Nothing to do then
return
}

let summaries: [MXRoomSummary] = recentRoomIds.compactMap {
guard let summary = session?.roomSummary(withRoomId: $0), summary.roomType == .room else {
return nil
}
return summary
}

var total: MXRoomListDataCounts?
if !summaries.isEmpty {
// compute total counts just before cutting the rooms array
total = MXStoreRoomListDataCounts(withRooms: summaries, total: nil)
}

self.data = MXRoomListData(rooms: summaries,
counts: MXStoreRoomListDataCounts(withRooms: summaries,
total: total),
paginationOptions: fetchOptions.paginationOptions)
self.recentRoomIds = recentRoomIds
}

func stop() {
removeAllDelegates()
removeDataObservers()
data = nil
recentRoomIds = []
}

// MARK: - Data observers

func addDataObservers() {
sessionSyncObserver = NotificationCenter.default.addObserver(forName:NSNotification.Name.mxSessionAccountDataDidChangeBreadcrumbs, object:session, queue:OperationQueue.main) { [weak self] (_) in
guard let self = self else { return }

self.refresh()
}
}

func removeDataObservers() {
if let sessionSyncObserver = sessionSyncObserver {
NotificationCenter.default.removeObserver(sessionSyncObserver)
}
}

}
4 changes: 4 additions & 0 deletions MatrixSDK/Data/RoomList/Common/MXRoomListDataSortable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ extension MXRoomListDataSortable {
// result.append(NSSortDescriptor(keyPath: \MXRoomSummaryProtocol.spaceChildInfo?.order, ascending: false))
// }

if sortOptions.alphabetical {
result.append(NSSortDescriptor(keyPath: \MXRoomSummaryProtocol.displayname, ascending: true))
}

if sortOptions.invitesFirst {
result.append(NSSortDescriptor(keyPath: \MXRoomSummaryProtocol.membership, ascending: true))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,10 @@ extension MXCoreDataRoomListDataFetcher: MXRoomListDataSortable {
func sortDescriptors(for sortOptions: MXRoomListDataSortOptions) -> [NSSortDescriptor] {
var result: [NSSortDescriptor] = []

if sortOptions.alphabetical {
result.append(NSSortDescriptor(keyPath: \MXRoomSummaryMO.s_displayName, ascending: true))
}

if sortOptions.invitesFirst {
result.append(NSSortDescriptor(keyPath: \MXRoomSummaryMO.s_membershipInt, ascending: true))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public class MXCoreDataRoomListDataManager: NSObject, MXRoomListDataManager {
session: session,
spaceService: spaceService)
}
if options.filterOptions.onlyBreadcrumbs {
return MXBreadcrumbsRoomListDataFetcher(fetchOptions: options, session: session)
}
guard let store = session?.store else {
fatalError("[MXCoreDataRoomListDataManager] No session store")
}
Expand Down
6 changes: 6 additions & 0 deletions MatrixSDK/Data/RoomList/MXRoomListDataFilterOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,15 @@ public struct MXRoomListDataFilterOptions: Equatable {
/// Flag to show only rooms that matches all the provided `dataTypes`. This has no effect when `onlySuggested` is `true`
public let strictMatches: Bool

///Flag to fetch and order rooms according room IDs stored in the `im.vector.setting.breadcrumbs` event within the user account data.
public let onlyBreadcrumbs: Bool
gileluard marked this conversation as resolved.
Show resolved Hide resolved

/// Initializer
/// - Parameters:
/// - dataTypes: data types to fetch. Pass `MXRoomListDataFilterOptions.emptyDataTypes` not to specify any.
/// - notDataTypes: data types not to fetch. Pass `MXRoomListDataFilterOptions.emptyDataTypes` not to specify any.
/// - onlySuggested: flag to filter only suggested rooms. Only `space` and `query` parameters are honored if true.
/// - onlyBreadcrumbs: flag to fetch and order rooms according room IDs stored in the `im.vector.setting.breadcrumbs` event within the user account data.
/// - query: search query
/// - space: active space
/// - showAllRoomsInHomeSpace: flag to show all rooms in home space (when `space` is not provided)
Expand All @@ -60,6 +64,7 @@ public struct MXRoomListDataFilterOptions: Equatable {
public init(dataTypes: MXRoomSummaryDataTypes = MXRoomListDataFilterOptions.emptyDataTypes,
notDataTypes: MXRoomSummaryDataTypes = [.hidden, .conferenceUser, .space],
onlySuggested: Bool = false,
onlyBreadcrumbs: Bool = false,
gileluard marked this conversation as resolved.
Show resolved Hide resolved
query: String? = nil,
space: MXSpace? = nil,
showAllRoomsInHomeSpace: Bool,
Expand All @@ -68,6 +73,7 @@ public struct MXRoomListDataFilterOptions: Equatable {
self.dataTypes = dataTypes
self.notDataTypes = notDataTypes
self.onlySuggested = onlySuggested
self.onlyBreadcrumbs = onlyBreadcrumbs
self.query = query
self.space = space
self.showAllRoomsInHomeSpace = showAllRoomsInHomeSpace
Expand Down
9 changes: 9 additions & 0 deletions MatrixSDK/Data/RoomList/MXRoomListDataSortOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,24 +47,33 @@ public struct MXRoomListDataSortOptions: Equatable {
/// Related fetcher will be refreshed automatically when updated.
public var unreadMessagesFirst: Bool

/// Flag to sort rooms alphabetically.
/// Related fetcher will be refreshed automatically when updated.
public var alphabetical: Bool
gileluard marked this conversation as resolved.
Show resolved Hide resolved

/// Initializer
/// - Parameters:
/// - sentStatus: flag to sort by sent status
/// - lastEventDate: flag to sort by last event date
/// - favoriteTag: Flag to sort by favorite tag order
/// - suggested: Flag to sort by suggested room flag
/// - alphabetical: Flag to sort rooms alphabetically
/// - missedNotificationsFirst: flag to sort by missed notification count
/// - unreadMessagesFirst: flag to sort by unread count
public init(invitesFirst: Bool = true,
sentStatus: Bool = true,
lastEventDate: Bool = true,
favoriteTag: Bool = false,
suggested: Bool = true,
alphabetical: Bool = false,
gileluard marked this conversation as resolved.
Show resolved Hide resolved
missedNotificationsFirst: Bool,
unreadMessagesFirst: Bool) {
self.invitesFirst = invitesFirst
self.sentStatus = sentStatus
self.lastEventDate = lastEventDate
self.favoriteTag = favoriteTag
self.suggested = suggested
self.alphabetical = alphabetical
self.missedNotificationsFirst = missedNotificationsFirst
self.unreadMessagesFirst = unreadMessagesFirst
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ public class MXStoreRoomListDataManager: NSObject, MXRoomListDataManager {
session: session,
spaceService: spaceService)
}
if options.filterOptions.onlyBreadcrumbs {
return MXBreadcrumbsRoomListDataFetcher(fetchOptions: options, session: session)
}
guard let store = session?.store else {
fatalError("[MXStoreRoomListDataManager] Session has no store")
}
Expand Down
2 changes: 2 additions & 0 deletions MatrixSDK/MXRestClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,15 @@ FOUNDATION_EXPORT NSString *const kMXAccountDataTypeIgnoredUserList;
FOUNDATION_EXPORT NSString *const kMXAccountDataTypeUserWidgets;
FOUNDATION_EXPORT NSString *const kMXAccountDataTypeIdentityServer;
FOUNDATION_EXPORT NSString *const kMXAccountDataTypeAcceptedTerms;
FOUNDATION_EXPORT NSString *const kMXAccountDataTypeBreadcrumbs;
FOUNDATION_EXPORT NSString *const kMXAccountDataTypeAcceptedTermsKey;

/**
Account data keys
*/
FOUNDATION_EXPORT NSString *const kMXAccountDataKeyIgnoredUser;
FOUNDATION_EXPORT NSString *const kMXAccountDataKeyIdentityServer;
FOUNDATION_EXPORT NSString *const kMXAccountDataTypeRecentRoomsKey;


/**
Expand Down
2 changes: 2 additions & 0 deletions MatrixSDK/MXRestClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@
NSString *const kMXAccountDataTypeUserWidgets = @"m.widgets";
NSString *const kMXAccountDataTypeIdentityServer = @"m.identity_server";
NSString *const kMXAccountDataTypeAcceptedTerms = @"m.accepted_terms";
NSString *const kMXAccountDataTypeBreadcrumbs = @"im.vector.setting.breadcrumbs";

/**
Account data keys
*/
NSString *const kMXAccountDataKeyIgnoredUser = @"ignored_users";
NSString *const kMXAccountDataKeyIdentityServer = @"base_url";
NSString *const kMXAccountDataTypeAcceptedTermsKey = @"accepted";
NSString *const kMXAccountDataTypeRecentRoomsKey = @"recent_rooms";

/**
Types of third party media.
Expand Down
5 changes: 5 additions & 0 deletions MatrixSDK/MXSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ FOUNDATION_EXPORT NSString *const kMXSessionAccountDataDidChangeNotification;
*/
FOUNDATION_EXPORT NSString *const kMXSessionAccountDataDidChangeIdentityServerNotification;

FOUNDATION_EXPORT NSString *const kMXSessionAccountDataDidChangeBreadcrumbsNotification;

/**
Posted when MXSession data have been corrupted. The listener must reload the session data with a full server sync.

Expand Down Expand Up @@ -1482,6 +1484,9 @@ typedef void (^MXOnBackgroundSyncFail)(NSError *error);
success:(void (^)(MXSession *session, NSString *baseURL, NSString *accessToken))success
failure:(void (^)(NSError *error))failure;

- (void)updateBreadcrumbsWithRoomWithId:(NSString *)roomId
success:(void (^)(void))success
failure:(void (^)(NSError *error))failure;

#pragma mark - Homeserver information

Expand Down
Loading