Merge commit '3d672a05b2a7117ade2e4e87bd2b5762063d7922' into feature/3977_merge_element_1_9_13

# Conflicts:
#	Config/AppVersion.xcconfig
#	Podfile.lock
#	Riot/Modules/Application/LegacyAppDelegate.m
#	Riot/Modules/Authentication/AuthenticationCoordinator.swift
#	Riot/Modules/Authentication/Legacy/LegacyAuthenticationCoordinator.swift
#	Riot/Modules/LaunchLoading/LaunchLoadingView.swift
#	Riot/Modules/LaunchLoading/LaunchLoadingView.xib
#	Riot/Modules/MatrixKit/Models/Account/MXKAccount.m
#	Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m
#	Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellProvider.m
#	Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellProvider.m
#	Riot/Modules/TabBar/MasterTabBarController.m
#	fastlane/Fastfile
This commit is contained in:
Frank Rotermund
2022-12-19 14:36:30 +01:00
245 changed files with 5346 additions and 1952 deletions
@@ -518,7 +518,6 @@
- (CGSize)textContentSize:(NSAttributedString*)attributedText removeVerticalInset:(BOOL)removeVerticalInset
{
static UITextView* measurementTextView = nil;
static UITextView* measurementTextViewWithoutInset = nil;
@@ -527,24 +526,23 @@
if (!measurementTextView)
{
measurementTextView = [[UITextView alloc] init];
measurementTextViewWithoutInset = [[UITextView alloc] init];
// Remove the container inset: this operation impacts only the vertical margin.
// Note: consider textContainer.lineFragmentPadding to remove horizontal margin
measurementTextViewWithoutInset.textContainerInset = UIEdgeInsetsZero;
}
// Select the right text view for measurement
UITextView *selectedTextView = (removeVerticalInset ? measurementTextViewWithoutInset : measurementTextView);
selectedTextView.frame = CGRectMake(0, 0, _maxTextViewWidth, 0);
selectedTextView.attributedText = attributedText;
// Force the layout manager to layout the text, fixes problems starting iOS 16
[selectedTextView.layoutManager ensureLayoutForTextContainer:selectedTextView.textContainer];
CGSize size = [selectedTextView sizeThatFits:selectedTextView.frame.size];
// Manage the case where a string attribute has a single paragraph with a left indent
// In this case, [UITextView sizeThatFits] ignores the indent and return the width
// of the text only.
@@ -557,8 +555,10 @@
{
size.width = size.width + paragraphStyle.headIndent;
}
return size;
}
return CGSizeZero;
}
@@ -985,8 +985,19 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
else if (nil == localEcho)
{
// Process here incoming events, and outgoing events sent from another device.
[self queueEventForProcessing:event withRoomState:roomState direction:MXTimelineDirectionForwards];
[self processQueuedEvents:nil];
if (self.threadId == nil && event.isInThread)
{
NSInteger index = [self indexOfCellDataWithEventId:event.relatesTo.eventId];
if (index != NSNotFound)
{
[self reloadNotifying:NO];
}
}
else
{
[self queueEventForProcessing:event withRoomState:roomState direction:MXTimelineDirectionForwards];
[self processQueuedEvents:nil];
}
}
}
}];
@@ -1373,6 +1384,11 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
// ignore the event
return NO;
}
// Ignore voice message related to an actual voice broadcast.
if (event.content[VoiceBroadcastSettings.voiceBroadcastContentKeyChunkType] != nil) {
return NO;
}
}
// Check for undecryptable messages that were sent while the user was not in the room and hide them
@@ -2358,15 +2374,61 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
// Update cell data we have received a read receipt for
NSArray *readEventIds = receiptEvent.readReceiptEventIds;
for (NSString* eventId in readEventIds)
if (RiotSettings.shared.enableThreads)
{
MXKRoomBubbleCellData *cellData = [self cellDataOfEventWithEventId:eventId];
if (cellData)
NSArray *readThreadIds = receiptEvent.readReceiptThreadIds;
for (int i = 0 ; i < readEventIds.count ; i++)
{
NSString *eventId = readEventIds[i];
MXKRoomBubbleCellData *cellData = [self cellDataOfEventWithEventId:eventId];
if (cellData)
{
if ([readThreadIds[i] isEqualToString:kMXEventUnthreaded])
{
// Unthreaded RR must be propagated through all threads.
[self.mxSession.threadingService allThreadsInRoomWithId:self.roomId onlyParticipated:NO completion:^(NSArray<id<MXThreadProtocol>> *threads) {
NSMutableArray *threadIds = [NSMutableArray arrayWithObject:kMXEventTimelineMain];
for (id<MXThreadProtocol> thread in threads)
{
[threadIds addObject:thread.id];
}
for (NSString *threadId in threadIds)
{
@synchronized(self->bubbles)
{
dispatch_group_enter(dispatchGroup);
[self addReadReceiptsForEvent:eventId threadId:threadId inCellDatas:self->bubbles startingAtCellData:cellData completion:^{
dispatch_group_leave(dispatchGroup);
}];
}
}
}];
}
else
{
NSString *threadId = readThreadIds[i];
@synchronized(self->bubbles)
{
dispatch_group_enter(dispatchGroup);
[self addReadReceiptsForEvent:eventId threadId:threadId inCellDatas:self->bubbles startingAtCellData:cellData completion:^{
dispatch_group_leave(dispatchGroup);
}];
}
}
}
}
}
else
{
// If
for (NSString *eventId in readEventIds)
{
MXKRoomBubbleCellData *cellData = [self cellDataOfEventWithEventId:eventId];
@synchronized(self->bubbles)
{
dispatch_group_enter(dispatchGroup);
[self addReadReceiptsForEvent:eventId inCellDatas:self->bubbles startingAtCellData:cellData completion:^{
[self addReadReceiptsForEvent:eventId threadId:kMXEventTimelineMain inCellDatas:self->bubbles startingAtCellData:cellData completion:^{
dispatch_group_leave(dispatchGroup);
}];
}
@@ -3512,7 +3574,10 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
@autoreleasepool
{
dispatch_group_enter(dispatchGroup);
[self addReadReceiptsForEvent:queuedEvent.event.eventId inCellDatas:self->bubblesSnapshot startingAtCellData:self->eventIdToBubbleMap[queuedEvent.event.eventId] completion:^{
[self addReadReceiptsForEvent:queuedEvent.event.eventId
threadId:queuedEvent.event.threadId
inCellDatas:self->bubblesSnapshot
startingAtCellData:self->eventIdToBubbleMap[queuedEvent.event.eventId] completion:^{
dispatch_group_leave(dispatchGroup);
}];
}
@@ -3667,16 +3732,22 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
If the event is not displayed, read receipts will be added to a previous displayed message.
@param eventId the id of the event.
@param threadId the Id of the thread related of the event.
@param cellDatas the working array of cell datas.
@param cellData the original cell data the event belongs to.
@param completion completion block
*/
- (void)addReadReceiptsForEvent:(NSString*)eventId inCellDatas:(NSArray<id<MXKRoomBubbleCellDataStoring>>*)cellDatas startingAtCellData:(id<MXKRoomBubbleCellDataStoring>)cellData completion:(void (^)(void))completion
- (void)addReadReceiptsForEvent:(NSString*)eventId
threadId:(NSString *)threadId
inCellDatas:(NSArray<id<MXKRoomBubbleCellDataStoring>>*)cellDatas
startingAtCellData:(id<MXKRoomBubbleCellDataStoring>)cellData
completion:(void (^)(void))completion
{
if (self.showBubbleReceipts)
{
if (self.room)
{
[self.room getEventReceipts:eventId sorted:YES completion:^(NSArray<MXReceiptData *> * _Nonnull readReceipts) {
[self.room getEventReceipts:eventId threadId:threadId sorted:YES completion:^(NSArray<MXReceiptData *> * _Nonnull readReceipts) {
if (readReceipts.count)
{
NSInteger cellDataIndex = [cellDatas indexOfObject:cellData];
@@ -3686,6 +3757,14 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
}
}
if (!RiotSettings.shared.enableThreads)
{
// If threads are disabled, we may have several threaded RR with same userId
// but different threadId within the same timeline.
// We just need to keep the latest one.
[self clearDuplicatedReadReceiptsInCellDatas:cellDatas];
}
if (completion)
{
completion();
@@ -3771,6 +3850,45 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
}
}
/**
Clear all potential duplicated RR with same user ID within a given list of cell data.
This is needed for client with threads disabled in order to clean threaded RRs.
@param cellDatas the working array of cell datas.
*/
- (void)clearDuplicatedReadReceiptsInCellDatas:(NSArray<id<MXKRoomBubbleCellDataStoring>>*)cellDatas
{
NSMutableSet<NSString *> *seenUserIds = [NSMutableSet set];
for (id<MXKRoomBubbleCellDataStoring> cellData in cellDatas.reverseObjectEnumerator)
{
if ([cellData isKindOfClass:MXKRoomBubbleCellData.class])
{
MXKRoomBubbleCellData *roomBubbleCellData = (MXKRoomBubbleCellData*)cellData;
for (MXKRoomBubbleComponent *component in roomBubbleCellData.bubbleComponents)
{
if (component.attributedTextMessage)
{
if (roomBubbleCellData.readReceipts[component.event.eventId])
{
NSArray<MXReceiptData*> *currentReadReceipts = roomBubbleCellData.readReceipts[component.event.eventId];
NSMutableArray<MXReceiptData*> *newReadReceipts = [NSMutableArray array];
for (MXReceiptData *readReceipt in currentReadReceipts)
{
if (![seenUserIds containsObject:readReceipt.userId])
{
[newReadReceipts addObject:readReceipt];
[seenUserIds addObject:readReceipt.userId];
}
}
[self updateCellData:roomBubbleCellData withReadReceipts:newReadReceipts forEventId:component.event.eventId];
}
}
}
}
}
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section