Merge branch 'release/1.9.1/master'

This commit is contained in:
Stefan Ceriu
2022-08-29 19:13:40 +03:00
51 changed files with 336 additions and 153 deletions
+19
View File
@@ -1,3 +1,22 @@
## Changes in 1.9.1 (2022-08-29)
🙌 Improvements
- Added Labs flag for the new App Layout. ([#6649](https://github.com/vector-im/element-ios/issues/6649))
🐛 Bugfixes
- Render the PIN entry screen correctly on landscape ([#6629](https://github.com/vector-im/element-ios/pull/6629))
- Ensure rest client async responses are processed on the main queue ([#6642](https://github.com/vector-im/element-ios/pull/6642))
- Stop waiting for biometric unlock if disabled system wide ([#5279](https://github.com/vector-im/element-ios/issues/5279))
- App Layout: added support for transparent avatar icons in the all chats screen ([#6556](https://github.com/vector-im/element-ios/issues/6556))
- App Layout: fixed reactions background in timeline ([#6557](https://github.com/vector-im/element-ios/issues/6557))
- App Layout: Removed Low Priority Rooms from Filters ([#6577](https://github.com/vector-im/element-ios/issues/6577))
- App Layout: Updated missing image for Onboarding screen page 2 ([#6624](https://github.com/vector-im/element-ios/issues/6624))
- App Layout: fixed limited number of invites in the All Chats screen ([#6625](https://github.com/vector-im/element-ios/issues/6625))
- Fix notification issues for threads. ([#6628](https://github.com/vector-im/element-ios/issues/6628))
## Changes in 1.9.0 (2022-08-24)
🙌 Improvements
+2 -2
View File
@@ -15,5 +15,5 @@
//
// Version
MARKETING_VERSION = 1.9.0
CURRENT_PROJECT_VERSION = 1.9.0
MARKETING_VERSION = 1.9.1
CURRENT_PROJECT_VERSION = 1.9.1
+5 -2
View File
@@ -419,8 +419,11 @@ final class BuildSettings: NSObject {
static let syncLocalContacts: Bool = false
// MARK: - New App Layout
static let newAppLayoutEnabled = true
static let newAppLayoutEnabled = false
static var isSideMenuActivated: Bool = enableSideMenu
static var isNewAppLayoutActivated: Bool = newAppLayoutEnabled
// MARK: - Device manager
static let deviceManagerEnabled = false
@@ -1,15 +1,17 @@
{
"images" : [
{
"filename" : "all_chats_onboarding2.svg",
"filename" : "all_chats_onboarding2.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "all_chats_onboarding2@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "all_chats_onboarding2@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

@@ -2,16 +2,7 @@
"images" : [
{
"filename" : "all_chats_edit_icon.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
"idiom" : "universal"
}
],
"info" : {
@@ -2,16 +2,7 @@
"images" : [
{
"filename" : "all_chats_empty_list_placeholder_icon.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
"idiom" : "universal"
}
],
"info" : {
@@ -2,16 +2,7 @@
"images" : [
{
"filename" : "all_chats_spaces_icon.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
"idiom" : "universal"
}
],
"info" : {
+1
View File
@@ -761,6 +761,7 @@ Tap the + to start adding people.";
"settings_labs_enable_auto_report_decryption_errors" = "Auto Report Decryption Errors";
"settings_labs_use_only_latest_user_avatar_and_name" = "Show latest avatar and name for users in message history";
"settings_labs_enable_live_location_sharing" = "Live location sharing - share current location (active development, and temporarily, locations persist in room history)";
"settings_labs_enable_new_app_layout" = "New Application Layout";
"settings_version" = "Version %@";
"settings_olm_version" = "Olm Version %@";
+3
View File
@@ -158,6 +158,7 @@ extension MXRestClient {
// MARK: - Private
@MainActor
private func getResponse<T>(_ callback: (@escaping (MXResponse<T>) -> Void) -> MXHTTPOperation) async throws -> T {
try await withCheckedThrowingContinuation { continuation in
_ = callback { response in
@@ -171,6 +172,7 @@ extension MXRestClient {
}
}
@MainActor
private func getResponse<T>(_ callback: (@escaping (T?) -> Void, @escaping (Error?) -> Void) -> MXHTTPOperation) async throws -> T {
try await withCheckedThrowingContinuation { continuation in
_ = callback { response in
@@ -186,6 +188,7 @@ extension MXRestClient {
}
}
@MainActor
private func getResponse<T, U, V>(_ callback: (@escaping (T?, U?, V?) -> Void, @escaping (Error?) -> Void) -> MXHTTPOperation) async throws -> (T?, U?, V?) {
try await withCheckedThrowingContinuation { continuation in
_ = callback { arg1, arg2, arg3 in
+4
View File
@@ -7351,6 +7351,10 @@ public class VectorL10n: NSObject {
public static var settingsLabsEnableLiveLocationSharing: String {
return VectorL10n.tr("Vector", "settings_labs_enable_live_location_sharing")
}
/// New Application Layout
public static var settingsLabsEnableNewAppLayout: String {
return VectorL10n.tr("Vector", "settings_labs_enable_new_app_layout")
}
/// Ring for group calls
public static var settingsLabsEnableRingingForGroupCalls: String {
return VectorL10n.tr("Vector", "settings_labs_enable_ringing_for_group_calls")
+14
View File
@@ -46,6 +46,8 @@ final class RiotSettings: NSObject {
private override init() {
super.init()
BuildSettings.isSideMenuActivated = BuildSettings.enableSideMenu && !newAppLayoutBetaEnabled
BuildSettings.isNewAppLayoutActivated = BuildSettings.newAppLayoutEnabled || newAppLayoutBetaEnabled
}
/// Indicate if UserDefaults suite has been migrated once.
@@ -381,9 +383,21 @@ final class RiotSettings: NSObject {
@UserDefault(key: "allChatsOnboardingHasBeenDisplayed", defaultValue: false, storage: defaults)
var allChatsOnboardingHasBeenDisplayed
// MARK: - New App Layout
@UserDefault(key: "newAppLayoutBetaEnabled", defaultValue: false, storage: defaults)
var newAppLayoutBetaEnabled {
didSet {
BuildSettings.isSideMenuActivated = BuildSettings.enableSideMenu && !newAppLayoutBetaEnabled
BuildSettings.isNewAppLayoutActivated = BuildSettings.newAppLayoutEnabled || newAppLayoutBetaEnabled
NotificationCenter.default.post(name: RiotSettings.newAppLayoutBetaToggleDidChange, object: self)
}
}
}
// MARK: - RiotSettings notification constants
extension RiotSettings {
public static let didUpdateLiveLocationSharingActivation = Notification.Name("RiotSettingsDidUpdateLiveLocationSharingActivation")
public static let newAppLayoutBetaToggleDidChange = Notification.Name("RiotSettingsNewAppLayoutBetaToggleDidChange")
}
+8 -2
View File
@@ -22,8 +22,14 @@ class BlackTheme: DarkTheme {
super.init()
self.identifier = ThemeIdentifier.black.rawValue
self.backgroundColor = UIColor(rgb: 0x000000)
self.baseColor = UIColor(rgb: 0x000000)
self.headerBackgroundColor = UIColor(rgb: 0x000000)
self.headerBorderColor = UIColor(rgb: 0x15191E)
}
override var baseColor: UIColor {
UIColor(rgb: 0x000000)
}
override var headerBackgroundColor: UIColor {
UIColor(rgb: 0x000000)
}
}
+6 -2
View File
@@ -26,7 +26,9 @@ class DarkTheme: NSObject, Theme {
var backgroundColor: UIColor = UIColor(rgb: 0x15191E)
var baseColor: UIColor = BuildSettings.newAppLayoutEnabled ? UIColor(rgb: 0x15191E) : UIColor(rgb: 0x21262C)
var baseColor: UIColor {
BuildSettings.isNewAppLayoutActivated ? UIColor(rgb: 0x15191E) : UIColor(rgb: 0x21262C)
}
var baseIconPrimaryColor: UIColor = UIColor(rgb: 0xEDF3FF)
var baseTextPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF)
var baseTextSecondaryColor: UIColor = UIColor(rgb: 0xA9B2BC)
@@ -35,7 +37,9 @@ class DarkTheme: NSObject, Theme {
var searchPlaceholderColor: UIColor = UIColor(rgb: 0xA9B2BC)
var searchResultHighlightColor: UIColor = UIColor(rgb: 0xFCC639).withAlphaComponent(0.3)
var headerBackgroundColor: UIColor = BuildSettings.newAppLayoutEnabled ? UIColor(rgb: 0x15191E) : UIColor(rgb: 0x21262C)
var headerBackgroundColor: UIColor {
BuildSettings.isNewAppLayoutActivated ? UIColor(rgb: 0x15191E) : UIColor(rgb: 0x21262C)
}
var headerBorderColor: UIColor = UIColor(rgb: 0x15191E)
var headerTextPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF)
var headerTextSecondaryColor: UIColor = UIColor(rgb: 0xA9B2BC)
@@ -26,7 +26,9 @@ class DefaultTheme: NSObject, Theme {
var backgroundColor: UIColor = UIColor(rgb: 0xFFFFFF)
var baseColor: UIColor = BuildSettings.newAppLayoutEnabled ? UIColor(rgb: 0xFFFFFF) : UIColor(rgb: 0xF5F7FA)
var baseColor: UIColor {
BuildSettings.isNewAppLayoutActivated ? UIColor(rgb: 0xFFFFFF) : UIColor(rgb: 0xF5F7FA)
}
var baseIconPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF)
var baseTextPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF)
var baseTextSecondaryColor: UIColor = UIColor(rgb: 0x8F97A3)
@@ -35,7 +37,9 @@ class DefaultTheme: NSObject, Theme {
var searchPlaceholderColor: UIColor = UIColor(rgb: 0x8F97A3)
var searchResultHighlightColor: UIColor = UIColor(rgb: 0xFCC639).withAlphaComponent(0.2)
var headerBackgroundColor: UIColor = BuildSettings.newAppLayoutEnabled ? UIColor(rgb: 0xFFFFFF) : UIColor(rgb: 0xF5F7FA)
var headerBackgroundColor: UIColor {
BuildSettings.isNewAppLayoutActivated ? UIColor(rgb: 0xFFFFFF) : UIColor(rgb: 0xF5F7FA)
}
var headerBorderColor: UIColor = UIColor(rgb: 0xE9EDF1)
var headerTextPrimaryColor: UIColor = UIColor(rgb: 0x17191C)
var headerTextSecondaryColor: UIColor = UIColor(rgb: 0x737D8C)
@@ -169,7 +173,7 @@ class DefaultTheme: NSObject, Theme {
searchBar.backgroundImage = UIImage() // Remove top and bottom shadow
searchBar.tintColor = self.tintColor
guard !BuildSettings.newAppLayoutEnabled else {
guard !BuildSettings.isNewAppLayoutActivated else {
return
}
@@ -34,6 +34,7 @@ struct SentryMonitoringClient {
options.dsn = Self.sentryDSN
// Collecting only 10% of all events
options.sampleRate = 0.1
options.tracesSampleRate = 0.1
options.beforeSend = { event in
@@ -91,7 +91,7 @@ final class AppCoordinator: NSObject, AppCoordinatorType {
// Setup user location services
_ = UserLocationServiceProvider.shared
if BuildSettings.enableSideMenu {
if BuildSettings.isSideMenuActivated {
self.addSideMenu()
}
@@ -105,6 +105,8 @@ final class AppCoordinator: NSObject, AppCoordinatorType {
}
}
NotificationCenter.default.addObserver(self, selector: #selector(self.newAppLayoutToggleDidChange(notification:)), name: RiotSettings.newAppLayoutBetaToggleDidChange, object: nil)
// NOTE: When split view is shown there can be no Matrix sessions ready. Keep this behavior or use a loading screen before showing the split view.
self.showSplitView()
MXLog.debug("[AppCoordinator] Showed split view")
@@ -160,6 +162,12 @@ final class AppCoordinator: NSObject, AppCoordinatorType {
ThemePublisher.shared.republish(themeIdPublisher: themeIdPublisher)
}
@objc private func newAppLayoutToggleDidChange(notification: Notification) {
if BuildSettings.isSideMenuActivated {
self.addSideMenu()
}
}
private func excludeAllItemsFromBackup() {
let manager = FileManager.default
+55 -10
View File
@@ -1114,21 +1114,66 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
threadId:(NSString *)threadId
sender:(NSString *)userId
{
if (roomId)
{
MXRoom *room = [self.mxSessions.firstObject roomWithRoomId:roomId];
if (room.summary.membership != MXMembershipJoin)
void(^sessionReadyBlock)(MXSession*) = ^(MXSession *session){
if (roomId)
{
Analytics.shared.joinedRoomTrigger = AnalyticsJoinedRoomTriggerNotification;
MXRoom *room = [session roomWithRoomId:roomId];
if (room.summary.membership != MXMembershipJoin)
{
Analytics.shared.joinedRoomTrigger = AnalyticsJoinedRoomTriggerNotification;
}
else
{
Analytics.shared.viewRoomTrigger = AnalyticsViewRoomTriggerNotification;
}
}
self.lastNavigatedRoomIdFromPush = roomId;
if (threadId)
{
if(![[MXKRoomDataSourceManager sharedManagerForMatrixSession:session] hasRoomDataSourceForRoom:roomId])
{
// the room having this thread probably was not opened before, paginate room messages to build threads
MXRoom *room = [session roomWithRoomId:roomId];
[room liveTimeline:^(id<MXEventTimeline> liveTimeline) {
[liveTimeline resetPagination];
[liveTimeline paginate:NSUIntegerMax direction:MXTimelineDirectionBackwards onlyFromStore:YES complete:^{
[liveTimeline resetPagination];
[self navigateToRoomById:roomId threadId:threadId sender:userId];
} failure:^(NSError * _Nonnull error) {
[self navigateToRoomById:roomId threadId:threadId sender:userId];
}];
}];
}
else
{
// the room has been opened before, we should be ok to continue
[self navigateToRoomById:roomId threadId:threadId sender:userId];
}
}
else
{
Analytics.shared.viewRoomTrigger = AnalyticsViewRoomTriggerNotification;
[self navigateToRoomById:roomId threadId:threadId sender:userId];
}
}
};
_lastNavigatedRoomIdFromPush = roomId;
[self navigateToRoomById:roomId threadId:threadId sender:userId];
MXSession *mxSession = self.mxSessions.firstObject;
if (mxSession.state >= MXSessionStateSyncInProgress)
{
sessionReadyBlock(mxSession);
}
else
{
// wait for session state to be sync in progress
__block id sessionStateObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXSessionStateDidChangeNotification object:mxSession queue:nil usingBlock:^(NSNotification * _Nonnull note) {
if (mxSession.state >= MXSessionStateSyncInProgress)
{
[[NSNotificationCenter defaultCenter] removeObserver:sessionStateObserver];
sessionReadyBlock(mxSession);
}
}];
}
}
#pragma mark - Badge Count
@@ -4212,7 +4257,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
}
// Need to set `showAllRoomsInHomeSpace` to `true` for the new App Layout
if (BuildSettings.newAppLayoutEnabled)
if (BuildSettings.isNewAppLayoutActivated)
{
RiotSettings.shared.showAllRoomsInHomeSpace = YES;
}
@@ -84,7 +84,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
_crossSigningBannerDisplay = CrossSigningBannerDisplayNone;
_secureBackupBannerDisplay = SecureBackupBannerDisplayNone;
_areSectionsShrinkable = !BuildSettings.newAppLayoutEnabled;
_areSectionsShrinkable = !BuildSettings.isNewAppLayoutActivated;
shrinkedSectionsBitMask = 0;
roomTagsListenerByUserId = [[NSMutableDictionary alloc] init];
@@ -758,7 +758,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
}
if (count && !(sectionType == RecentsDataSourceSectionTypeInvites) && !BuildSettings.newAppLayoutEnabled)
if (count && !(sectionType == RecentsDataSourceSectionTypeInvites) && !BuildSettings.isNewAppLayoutActivated)
{
NSString *roomCount = [NSString stringWithFormat:@" %tu", count];
@@ -987,7 +987,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
sectionHeader.bottomView = nil;
}
if (!BuildSettings.newAppLayoutEnabled || !sectionHeader.bottomView)
if (!BuildSettings.isNewAppLayoutActivated || !sectionHeader.bottomView)
{
// Add label
frame.size.height = RECENTSDATASOURCE_DEFAULT_SECTION_HEADER_HEIGHT - 10;
@@ -1101,7 +1101,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
{
RecentsInvitesTableViewCell *tableViewCell = [tableView dequeueReusableCellWithIdentifier:[RecentsInvitesTableViewCell defaultReuseIdentifier]];
tableViewCell.invitesCount = self.recentsListService.invitedRoomListData.counts.numberOfRooms;
tableViewCell.invitesCount = self.recentsListService.invitedRoomListData.counts.total.numberOfRooms;
return tableViewCell;
}
@@ -132,7 +132,7 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
if let fetcher = conversationRoomListDataFetcherForRooms, fetcherTypes.contains(.conversationRooms) {
result.append(fetcher)
}
if let fetcher = lowPriorityRoomListDataFetcher, fetcherTypes.contains(.lowPriority) {
if let fetcher = lowPriorityRoomListDataFetcher, fetcherTypes.contains(.lowPriority), shouldShowLowPriority {
result.append(fetcher)
}
if let fetcher = serverNoticeRoomListDataFetcher, fetcherTypes.contains(.serverNotice) {
@@ -482,7 +482,7 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
}
private var shouldShowLowPriority: Bool {
return fetcherTypesForMode[mode]?.contains(.lowPriority) ?? false
return ((mode != .allChats) || !AllChatsLayoutSettingsManager.shared.hasAnActiveFilter) && fetcherTypesForMode[mode]?.contains(.lowPriority) ?? false
}
private var shouldShowServerNotice: Bool {
@@ -37,7 +37,7 @@ class PublicRoomContextMenuProvider: NSObject {
}
roomViewController.isContextPreview = true
RoomPreviewDataSource.load(withRoomId: room.roomId, andMatrixSession: session) { [weak roomViewController] roomDataSource in
RoomPreviewDataSource.load(withRoomId: room.roomId, threadId: nil, andMatrixSession: session) { [weak roomViewController] roomDataSource in
guard let dataSource = roomDataSource as? RoomPreviewDataSource else {
return
}
@@ -57,7 +57,7 @@ class RecentCellContextMenuProvider: NSObject {
}
roomViewController.isContextPreview = true
RoomPreviewDataSource.load(withRoomId: room.roomId, andMatrixSession: session) { [weak roomViewController] roomDataSource in
RoomPreviewDataSource.load(withRoomId: room.roomId, threadId: nil, andMatrixSession: session) { [weak roomViewController] roomDataSource in
guard let dataSource = roomDataSource as? RoomPreviewDataSource else {
return
}
@@ -146,7 +146,7 @@
[self updateSearch];
if (BuildSettings.newAppLayoutEnabled)
if (BuildSettings.isNewAppLayoutActivated)
{
[self.searchBar vc_searchTextField].backgroundColor = nil;
[self vc_setLargeTitleDisplayMode: UINavigationItemLargeTitleDisplayModeAutomatic];
@@ -105,6 +105,11 @@ final class AllChatsLayoutSettingsManager: NSObject {
}
}
/// `true` if filters are activated in the All Chats Layout screen and a filter other than `.all` is active
var hasAnActiveFilter: Bool {
return !allChatLayoutSettings.filters.isEmpty && !activeFilters.isEmpty && activeFilters != .all
}
// MARK: - Private
private func track(activeFilters: AllChatsLayoutFilterType?) {
+5
View File
@@ -80,6 +80,11 @@
{
[super viewDidLoad];
if (!BuildSettings.isNewAppLayoutActivated)
{
[self.tabBarController vc_setLargeTitleDisplayMode:UINavigationItemLargeTitleDisplayModeNever];
}
self.roomListDataReady = NO;
self.view.accessibilityIdentifier = @"HomeVCView";
@@ -63,7 +63,7 @@ final class UserVerificationSessionStatusCell: UITableViewCell, NibReusable, The
func update(theme: Theme) {
self.theme = theme
self.backgroundColor = theme.headerBackgroundColor
self.backgroundColor = theme.colors.system
self.sessionNameLabel.textColor = theme.textPrimaryColor
self.updateStatusTextColor()
}
@@ -261,10 +261,11 @@ extern NSString *const kMXKRoomDataSourceTimelineErrorErrorKey;
the room data source is created.
@param roomId the id of the room to get data from.
@param threadId the id of the thread to load. If provided, thread data source will be loaded from the room specified with `roomId`.
@param mxSession the Matrix session to get data from.
@param onComplete a block providing the newly created instance.
*/
+ (void)loadRoomDataSourceWithRoomId:(NSString*)roomId andMatrixSession:(MXSession*)mxSession onComplete:(void (^)(id roomDataSource))onComplete;
+ (void)loadRoomDataSourceWithRoomId:(NSString*)roomId threadId:(NSString*)threadId andMatrixSession:(MXSession*)mxSession onComplete:(void (^)(id roomDataSource))onComplete;
/**
Asynchronously create adata source to serve data corresponding to an event in the
@@ -306,10 +307,11 @@ extern NSString *const kMXKRoomDataSourceTimelineErrorErrorKey;
Initialise the data source to serve data corresponding to the passed room.
@param roomId the id of the room to get data from.
@param threadId the id of the thread to initialize. If provided, thread data source will be initialized from the room specified with `roomId`.
@param mxSession the Matrix session to get data from.
@return the newly created instance.
*/
- (instancetype)initWithRoomId:(NSString*)roomId andMatrixSession:(MXSession*)mxSession;
- (instancetype)initWithRoomId:(NSString*)roomId andMatrixSession:(MXSession*)mxSession threadId:(NSString*)threadId;
/**
Initialise the data source to serve data corresponding to an event in the
@@ -208,9 +208,9 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
@implementation MXKRoomDataSource
+ (void)loadRoomDataSourceWithRoomId:(NSString*)roomId andMatrixSession:(MXSession*)mxSession onComplete:(void (^)(id roomDataSource))onComplete
+ (void)loadRoomDataSourceWithRoomId:(NSString*)roomId threadId:(NSString*)threadId andMatrixSession:(MXSession*)mxSession onComplete:(void (^)(id roomDataSource))onComplete
{
MXKRoomDataSource *roomDataSource = [[self alloc] initWithRoomId:roomId andMatrixSession:mxSession];
MXKRoomDataSource *roomDataSource = [[self alloc] initWithRoomId:roomId andMatrixSession:mxSession threadId:threadId];
[self ensureSessionStateForDataSource:roomDataSource initialEventId:nil andMatrixSession:mxSession onComplete:onComplete];
}
@@ -284,7 +284,7 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
}
}
- (instancetype)initWithRoomId:(NSString *)roomId andMatrixSession:(MXSession *)matrixSession
- (instancetype)initWithRoomId:(NSString *)roomId andMatrixSession:(MXSession *)matrixSession threadId:(NSString *)threadId
{
self = [super initWithMatrixSession:matrixSession];
if (self)
@@ -292,6 +292,7 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
MXLogVerbose(@"[MXKRoomDataSource][%p] initWithRoomId: %@", self, roomId);
_roomId = roomId;
_threadId = threadId;
_secondaryRoomEventTypes = @[
kMXEventTypeStringCallInvite,
kMXEventTypeStringCallCandidates,
@@ -368,7 +369,7 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
- (instancetype)initWithRoomId:(NSString*)roomId initialEventId:(NSString*)initialEventId2 threadId:(NSString*)threadId andMatrixSession:(MXSession*)mxSession
{
self = [self initWithRoomId:roomId andMatrixSession:mxSession];
self = [self initWithRoomId:roomId andMatrixSession:mxSession threadId:threadId];
if (self)
{
if (initialEventId2)
@@ -376,7 +377,6 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
initialEventId = initialEventId2;
_isLive = NO;
}
_threadId = threadId;
}
return self;
@@ -553,6 +553,7 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
}
self.room = nil;
self.thread = nil;
self.secondaryRoom = nil;
}
@@ -584,7 +585,7 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
- (void)destroy
{
MXLogDebug(@"[MXKRoomDataSource][%p] Destroy - room id: %@", self, _roomId);
MXLogDebug(@"[MXKRoomDataSource][%p] Destroy - room id: %@ - thread id: %@", self, _roomId, _threadId);
[self unregisterScanManagerNotifications];
[self unregisterReactionsChangeListener];
@@ -2848,11 +2849,14 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
- (void)setState:(MXKDataSourceState)newState
{
self->state = newState;
if (self.delegate && [self.delegate respondsToSelector:@selector(dataSource:didStateChange:)])
if (self->state != newState)
{
[self.delegate dataSource:self didStateChange:self->state];
self->state = newState;
if (self.delegate && [self.delegate respondsToSelector:@selector(dataSource:didStateChange:)])
{
[self.delegate dataSource:self didStateChange:self->state];
}
}
}
@@ -78,6 +78,13 @@ typedef enum : NSUInteger {
*/
- (void)reset;
/**
Flag indicating the manager has a room data source for a given room id.
@param roomId the room id to check.
*/
- (BOOL)hasRoomDataSourceForRoom:(NSString*)roomId;
/**
Get a room data source corresponding to a room id.
@@ -191,6 +191,11 @@ static Class _roomDataSourceClass;
}
}
- (BOOL)hasRoomDataSourceForRoom:(NSString *)roomId
{
return roomDataSources[roomId] != nil;
}
- (void)roomDataSourceForRoom:(NSString *)roomId create:(BOOL)create onComplete:(void (^)(MXKRoomDataSource *roomDataSource))onComplete
{
NSParameterAssert(roomId);
@@ -200,7 +205,7 @@ static Class _roomDataSourceClass;
if (!roomDataSource && create && roomId)
{
[_roomDataSourceClass loadRoomDataSourceWithRoomId:roomId andMatrixSession:mxSession onComplete:^(id roomDataSource) {
[_roomDataSourceClass loadRoomDataSourceWithRoomId:roomId threadId:nil andMatrixSession:mxSession onComplete:^(id roomDataSource) {
[self addRoomDataSource:roomDataSource];
onComplete(roomDataSource);
}];
@@ -73,8 +73,8 @@ final class ReactionsMenuView: UIView, Themable, NibLoadable {
// MARK: - Public
func update(theme: Theme) {
self.reactionsBackgroundView.backgroundColor = theme.headerBackgroundColor
self.moreReactionsBackgroundView.backgroundColor = theme.headerBackgroundColor
self.reactionsBackgroundView.backgroundColor = theme.colors.system
self.moreReactionsBackgroundView.backgroundColor = theme.colors.system
self.moreReactionsButton.tintColor = theme.tintColor
}
@@ -68,9 +68,9 @@ const CGFloat kTypingCellHeight = 24;
@implementation RoomDataSource
- (instancetype)initWithRoomId:(NSString *)roomId andMatrixSession:(MXSession *)matrixSession
- (instancetype)initWithRoomId:(NSString *)roomId andMatrixSession:(MXSession *)matrixSession threadId:(NSString *)threadId
{
self = [super initWithRoomId:roomId andMatrixSession:matrixSession];
self = [super initWithRoomId:roomId andMatrixSession:matrixSession threadId:threadId];
if (self)
{
// Replace default Cell data class
@@ -15,15 +15,31 @@
//
import Foundation
import UIKit
@objcMembers
public class ThreadDataSource: RoomDataSource {
private typealias ThreadID = String
/// Map of cached data sources. Keys are thread identifiers.
private static var dataSourceCache: [ThreadID: ThreadDataSource] = [:]
public override func finalizeInitialization() {
super.finalizeInitialization()
showReadMarker = false
showBubbleReceipts = false
showTypingRow = false
NotificationCenter.default.addObserver(self,
selector: #selector(didReceiveMemoryWarning),
name: UIApplication.didReceiveMemoryWarningNotification,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(didLeaveRoom(_:)),
name: .mxSessionDidLeaveRoom,
object: nil)
}
public override var showReadMarker: Bool {
@@ -41,5 +57,47 @@ public class ThreadDataSource: RoomDataSource {
_ = newValue
}
}
public override class func load(withRoomId roomId: String!,
initialEventId: String!,
threadId: String!,
andMatrixSession mxSession: MXSession!,
onComplete: ((Any?) -> Void)!) {
if let dataSource = dataSourceCache[threadId] {
onComplete(dataSource)
return
}
super.load(withRoomId: roomId, initialEventId: initialEventId, threadId: threadId, andMatrixSession: mxSession) { dataSource in
if let dataSource = dataSource as? ThreadDataSource {
Self.dataSourceCache[threadId] = dataSource
}
onComplete(dataSource)
}
}
@objc
private func didReceiveMemoryWarning() {
MXLog.debug("[ThreadDataSource] didReceiveMemoryWarning. Will reload not active data sources in cache.")
Self.dataSourceCache.forEach {
if $1.delegate == nil {
$1.reload()
}
}
}
@objc
private func didLeaveRoom(_ notification: Notification) {
MXLog.debug("[ThreadDataSource] didReceiveMemoryWarning. Will reload not active data sources in cache.")
guard let session = notification.object as? MXSession,
session == mxSession,
let roomId = notification.userInfo?[kMXSessionNotificationRoomIdKey] as? String else {
return
}
let threadIds = Array(Self.dataSourceCache.filter { $1.roomId == roomId }.keys)
threadIds.forEach { Self.dataSourceCache.removeValue(forKey: $0) }
}
}
+3 -1
View File
@@ -291,6 +291,8 @@
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setToolbarHidden:YES animated:NO];
// Observe server sync process at room data source level too
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMatrixSessionChange) name:kMXKRoomDataSourceSyncStatusChanged object:nil];
@@ -339,7 +341,7 @@
_bubblesTableView.hidden = NO;
}
if (BuildSettings.newAppLayoutEnabled)
if (BuildSettings.isNewAppLayoutActivated)
{
[self vc_setLargeTitleDisplayMode: UINavigationItemLargeTitleDisplayModeNever];
}
+5 -2
View File
@@ -67,7 +67,10 @@ final class RoomCoordinator: NSObject, RoomCoordinatorProtocol {
var canReleaseRoomDataSource: Bool {
// If the displayed data is not a preview, let the manager release the room data source
// (except if the view controller has the room data source ownership).
return self.parameters.previewData == nil && self.roomViewController.roomDataSource != nil && self.roomViewController.hasRoomDataSourceOwnership == false
return self.parameters.previewData == nil
&& self.roomViewController.roomDataSource != nil
&& self.roomViewController.roomDataSource.threadId == nil
&& self.roomViewController.hasRoomDataSourceOwnership == false
}
// MARK: - Setup
@@ -238,7 +241,7 @@ final class RoomCoordinator: NSObject, RoomCoordinatorProtocol {
self.roomViewController.displayRoom(threadDataSource)
// Give the data source ownership to the room view controller.
self.roomViewController.hasRoomDataSourceOwnership = true
self.roomViewController.hasRoomDataSourceOwnership = false
self.mxSession?.updateBreadcrumbsWithRoom(withId: roomId, success: nil, failure: nil)
@@ -47,7 +47,7 @@ final class RoomInfoCoordinator: NSObject, RoomInfoCoordinatorType {
let files = RoomFilesViewController()
files.finalizeInit()
files.screenTracker = AnalyticsScreenTracker(screen: .roomUploads)
MXKRoomDataSource.load(withRoomId: self.room.roomId, andMatrixSession: self.session) { (dataSource) in
MXKRoomDataSource.load(withRoomId: self.room.roomId, threadId: nil, andMatrixSession: self.session) { (dataSource) in
guard let dataSource = dataSource as? MXKRoomDataSource else { return }
dataSource.filterMessagesWithURL = true
dataSource.finalizeInitialization()
+1
View File
@@ -5687,6 +5687,7 @@ static CGSize kThreadListBarButtonItemImageSize;
if (self.isContextPreview)
{
[RoomPreviewDataSource loadRoomDataSourceWithRoomId:self.roomDataSource.roomId
threadId:nil
andMatrixSession:self.mainSession
onComplete:^(RoomPreviewDataSource *roomDataSource)
{
@@ -130,7 +130,7 @@ final class KeyVerificationCellInnerContentView: UIView, NibLoadable {
// MARK: - Public
func update(theme: Theme) {
self.backgroundColor = theme.headerBackgroundColor
self.backgroundColor = theme.colors.system
self.titleLabel.textColor = theme.textPrimaryColor
self.otherUserInformationLabel.textColor = theme.textSecondaryColor
@@ -87,6 +87,6 @@ final class RoomReactionActionViewCell: UICollectionViewCell, NibReusable, Thema
self.actionLabel.textColor = self.theme?.textSecondaryColor
self.reactionBackgroundView.layer.borderWidth = 0.0
self.reactionBackgroundView.backgroundColor = self.theme?.headerBackgroundColor
self.reactionBackgroundView.backgroundColor = self.theme?.colors.system
}
}
@@ -79,6 +79,6 @@ final class RoomReactionImageViewCell: UICollectionViewCell, NibReusable, Themab
self.imageView.tintColor = self.theme?.textSecondaryColor
self.reactionBackgroundView.layer.borderWidth = 0.0
self.reactionBackgroundView.backgroundColor = self.theme?.headerBackgroundColor
self.reactionBackgroundView.backgroundColor = self.theme?.colors.system
}
}
@@ -97,7 +97,7 @@ final class RoomReactionViewCell: UICollectionViewCell, NibReusable, Themable {
reactionBackgroundColor = self.theme?.tintBackgroundColor
reactionBackgroundBorderWidth = Constants.selectedBorderWidth
} else {
reactionBackgroundColor = self.theme?.headerBackgroundColor
reactionBackgroundColor = self.theme?.colors.system
reactionBackgroundBorderWidth = 0.0
}
@@ -127,6 +127,10 @@ final class PinCodePreferences: NSObject {
var canUseBiometricsToUnlock: Bool? {
get {
guard isBiometricsAvailable == true else {
return false
}
do {
return try store.bool(forKey: StoreKeys.canUseBiometricsToUnlock)
} catch let error {
@@ -95,13 +95,8 @@ final class SetPinCoordinatorBridgePresenter: NSObject {
let setPinCoordinator = SetPinCoordinator(session: self.session, viewMode: self.viewMode, pinCodePreferences: .shared)
setPinCoordinator.delegate = self
guard let view = setPinCoordinator.toPresentable().view else { return }
pinCoordinatorWindow.addSubview(view)
view.leadingAnchor.constraint(equalTo: pinCoordinatorWindow.leadingAnchor, constant: 0).isActive = true
view.trailingAnchor.constraint(equalTo: pinCoordinatorWindow.trailingAnchor, constant: 0).isActive = true
view.topAnchor.constraint(equalTo: pinCoordinatorWindow.topAnchor, constant: 0).isActive = true
view.bottomAnchor.constraint(equalTo: pinCoordinatorWindow.bottomAnchor, constant: 0).isActive = true
pinCoordinatorWindow.rootViewController = setPinCoordinator.toPresentable()
pinCoordinatorWindow.makeKeyAndVisible()
setPinCoordinator.start()
+31 -1
View File
@@ -172,7 +172,8 @@ typedef NS_ENUM(NSUInteger, LABS_ENABLE)
LABS_ENABLE_RINGING_FOR_GROUP_CALLS_INDEX = 0,
LABS_ENABLE_THREADS_INDEX,
LABS_ENABLE_AUTO_REPORT_DECRYPTION_ERRORS,
LABS_ENABLE_LIVE_LOCATION_SHARING
LABS_ENABLE_LIVE_LOCATION_SHARING,
LABS_ENABLE_NEW_APP_LAYOUT
};
typedef NS_ENUM(NSUInteger, SECURITY)
@@ -595,6 +596,7 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
{
[sectionLabs addRowWithTag:LABS_ENABLE_LIVE_LOCATION_SHARING];
}
[sectionLabs addRowWithTag:LABS_ENABLE_NEW_APP_LAYOUT];
sectionLabs.headerTitle = [VectorL10n settingsLabs];
if (sectionLabs.hasAnyRows)
{
@@ -1497,6 +1499,21 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
return labelAndSwitchCell;
}
- (UITableViewCell *)buildNewAppLayoutCellForTableView:(UITableView*)tableView
atIndexPath:(NSIndexPath*)indexPath
{
MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath];
labelAndSwitchCell.mxkLabel.text = [VectorL10n settingsLabsEnableNewAppLayout];
labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.newAppLayoutBetaEnabled;
labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor;
labelAndSwitchCell.mxkSwitch.enabled = YES;
[labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleEnableNewAppLayout:) forControlEvents:UIControlEventTouchUpInside];
return labelAndSwitchCell;
}
#pragma mark - 3Pid Add
- (void)showAuthenticationIfNeededForAdding:(MX3PIDMedium)medium withSession:(MXSession*)session completion:(void (^)(NSDictionary* authParams))completion
@@ -2532,6 +2549,10 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
{
cell = [self buildLiveLocationSharingCellForTableView:tableView atIndexPath:indexPath];
}
else if (row == LABS_ENABLE_NEW_APP_LAYOUT)
{
cell = [self buildNewAppLayoutCellForTableView:tableView atIndexPath:indexPath];
}
}
else if (section == SECTION_TAG_SECURITY)
{
@@ -3971,6 +3992,15 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
RiotSettings.shared.enableLiveLocationSharing = sender.isOn;
}
- (void)toggleEnableNewAppLayout:(UISwitch *)sender
{
if (sender.isOn)
{
RiotSettings.shared.showAllRoomsInHomeSpace = YES;
}
RiotSettings.shared.newAppLayoutBetaEnabled = sender.isOn;
}
#pragma mark - TextField listener
- (IBAction)textFieldDidChange:(id)sender
@@ -227,7 +227,7 @@ final class SplitViewCoordinator: NSObject, SplitViewCoordinatorType {
}
let existingRoomCoordinatorWithSameRoomId = self.detailModules.first { presentable -> Bool in
if let currentRoomCoordinator = presentable as? RoomCoordinatorProtocol {
if let currentRoomCoordinator = presentable as? RoomCoordinatorProtocol, currentRoomCoordinator.threadId == nil {
return currentRoomCoordinator.roomId == roomCoordinator.roomId
}
return false
+7 -7
View File
@@ -156,7 +156,7 @@
[self userInterfaceThemeDidChange];
}
self.tabBar.hidden = BuildSettings.newAppLayoutEnabled;
self.tabBar.hidden = BuildSettings.isNewAppLayoutActivated;
}
- (void)viewDidAppear:(BOOL)animated
@@ -213,8 +213,8 @@
}
[[AppDelegate theDelegate] checkAppVersion];
if (BuildSettings.newAppLayoutEnabled && !RiotSettings.shared.allChatsOnboardingHasBeenDisplayed)
if (BuildSettings.isNewAppLayoutActivated && !RiotSettings.shared.allChatsOnboardingHasBeenDisplayed)
{
[self showAllChatsOnboardingScreen];
}
@@ -633,7 +633,7 @@
{
if (roomParentId) {
NSString *parentName = [mxSession roomSummaryWithRoomId:roomParentId].displayname;
if (!BuildSettings.newAppLayoutEnabled)
if (!BuildSettings.isNewAppLayoutActivated)
{
NSMutableArray<NSString *> *breadcrumbs = [[NSMutableArray alloc] initWithObjects:parentName, nil];
@@ -649,7 +649,7 @@
}
else
{
if (!BuildSettings.newAppLayoutEnabled)
if (!BuildSettings.isNewAppLayoutActivated)
{
titleView.breadcrumbView.breadcrumbs = @[];
}
@@ -661,7 +661,7 @@
- (void)updateSideMenuNotifcationIcon
{
if (BuildSettings.newAppLayoutEnabled) { return; }
if (BuildSettings.isNewAppLayoutActivated) { return; }
BOOL displayNotification = NO;
@@ -693,7 +693,7 @@
-(void)setupTitleView
{
if (!BuildSettings.newAppLayoutEnabled)
if (!BuildSettings.isNewAppLayoutActivated)
{
titleView = [MainTitleView new];
self.navigationItem.titleView = titleView;
+24 -9
View File
@@ -116,13 +116,15 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
self.addMatrixSessionToMasterTabBarController(userSession.matrixSession)
}
if BuildSettings.enableSideMenu {
if BuildSettings.isSideMenuActivated {
self.setupSideMenuGestures()
}
self.registerUserSessionsServiceNotifications()
self.registerSessionChange()
NotificationCenter.default.addObserver(self, selector: #selector(self.newAppLayoutToggleDidChange(notification:)), name: RiotSettings.newAppLayoutBetaToggleDidChange, object: nil)
self.updateMasterTabBarController(with: spaceId, forceReload: true)
} else {
self.updateMasterTabBarController(with: spaceId)
@@ -239,6 +241,15 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
// MARK: - Private methods
@objc private func newAppLayoutToggleDidChange(notification: Notification) {
self.masterTabBarController = nil
start()
// updateMasterTabBarController(with: self.currentSpaceId, forceReload: true)
// createLeftButtonItem(for: self.masterTabBarController)
// createRightButtonItem(for: self.masterTabBarController)
// popToHome(animated: true, completion: nil)
}
private func createMasterTabBarController() -> MasterTabBarController {
let tabBarController = MasterTabBarController()
@@ -367,10 +378,10 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
private func updateTabControllers(for tabBarController: MasterTabBarController, showCommunities: Bool) {
var viewControllers: [UIViewController] = []
let homeViewController = BuildSettings.newAppLayoutEnabled ? self.createAllChatsViewController() : self.createHomeViewController()
let homeViewController = BuildSettings.isNewAppLayoutActivated ? self.createAllChatsViewController() : self.createHomeViewController()
viewControllers.append(homeViewController)
if !BuildSettings.newAppLayoutEnabled {
if !BuildSettings.isNewAppLayoutActivated {
if RiotSettings.shared.homeScreenShowFavouritesTab {
let favouritesViewController = self.createFavouritesViewController()
viewControllers.append(favouritesViewController)
@@ -703,14 +714,15 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
// MARK: Navigation bar items management
private weak var rightMenuAvatarView: AvatarView?
private weak var rightMenuButton: UIButton?
private func createLeftButtonItem(for viewController: UIViewController) {
guard !BuildSettings.newAppLayoutEnabled else {
guard !BuildSettings.isNewAppLayoutActivated else {
createAvatarButtonItem(for: viewController)
return
}
guard BuildSettings.enableSideMenu else {
guard BuildSettings.isSideMenuActivated else {
let settingsBarButtonItem: MXKBarButtonItem = MXKBarButtonItem(image: Asset.Images.settingsIcon.image, style: .plain) { [weak self] in
self?.showSettings()
}
@@ -729,7 +741,7 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
}
private func createRightButtonItem(for viewController: UIViewController) {
guard !BuildSettings.newAppLayoutEnabled else {
guard !BuildSettings.isNewAppLayoutActivated else {
return
}
@@ -776,6 +788,7 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
button.showsMenuAsPrimaryAction = true
button.autoresizingMask = [.flexibleHeight, .flexibleWidth]
view.addSubview(button)
self.rightMenuButton = button
let avatarView = UserAvatarView(frame: view.bounds.inset(by: UIEdgeInsets(top: 7, left: 7, bottom: 7, right: 7)))
avatarView.isUserInteractionEnabled = false
@@ -786,16 +799,18 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
if let avatar = userAvatarViewData(from: currentMatrixSession) {
avatarView.fill(with: avatar)
button.setImage(nil, for: .normal)
}
viewController.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: view)
}
private func updateAvatarButtonItem() {
guard let avatarView = rightMenuAvatarView, let avatar = userAvatarViewData(from: currentMatrixSession) else {
guard let avatarView = rightMenuAvatarView, let button = rightMenuButton, let avatar = userAvatarViewData(from: currentMatrixSession) else {
return
}
button.setImage(nil, for: .normal)
avatarView.fill(with: avatar)
}
@@ -890,7 +905,7 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
private var windowOverlay: WindowOverlayPresenter?
func showCoachMessageIfNeeded(with session: MXSession) {
guard !BuildSettings.newAppLayoutEnabled else {
guard !BuildSettings.isNewAppLayoutActivated else {
// Showing coach message makes no sense with the new App Layout
return
}
@@ -937,7 +952,7 @@ extension TabBarCoordinator: MasterTabBarControllerDelegate {
}
func masterTabBarController(_ masterTabBarController: MasterTabBarController!, needsSideMenuIconWithNotification displayNotification: Bool) {
guard BuildSettings.enableSideMenu else {
guard BuildSettings.isSideMenuActivated else {
return
}
@@ -93,7 +93,7 @@ private final class StubMXKRoomDataSource: MXKRoomDataSource {
private final class FakeMXKRoomDataSource: MXKRoomDataSource {
class func make() throws -> FakeMXKRoomDataSource {
let dataSource = try XCTUnwrap(FakeMXKRoomDataSource(roomId: "!foofoofoofoofoofoo:matrix.org", andMatrixSession: nil))
let dataSource = try XCTUnwrap(FakeMXKRoomDataSource(roomId: "!foofoofoofoofoofoo:matrix.org", andMatrixSession: nil, threadId: nil))
dataSource.registerCellDataClass(CollapsibleBubbleCellData.self, forCellIdentifier: kMXKRoomBubbleCellDataIdentifier)
dataSource.eventFormatter = CountingEventFormatter(matrixSession: nil)
return dataSource