Skip to content

Commit

Permalink
Merge branch 'master' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
pixlwave committed Jan 26, 2023
2 parents 87d8aec + 8bc7134 commit 78a4272
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 61 deletions.
12 changes: 12 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## Changes in 1.9.17 (2023-01-26)

🙌 Improvements

- Analytics: Ensure E2EE never tracks UnknownError ([#7304](https://github.com/vector-im/element-ios/pull/7304))

🐛 Bugfixes

- Fix a deadlock when updating the summary of a room that has a voice broadcast. ([#7300](https://github.com/vector-im/element-ios/pull/7300))
- Space Switcher: Fix a bug where the avatars would all be the same. ([#7305](https://github.com/vector-im/element-ios/issues/7305))


## Changes in 1.9.16 (2023-01-24)

✨ Features
Expand Down
4 changes: 0 additions & 4 deletions Riot/Modules/Analytics/DecryptionFailure.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@

import AnalyticsEvents

/// Failure reasons as defined in https://docs.google.com/document/d/1es7cTCeJEXXfRCTRgZerAM2Wg5ZerHjvlpfTW-gsOfI.
@objc enum DecryptionFailureReason: Int {
case unspecified
case olmKeysNotSent
case olmIndexError
case unexpected

var errorName: AnalyticsEvent.Error.Name {
switch self {
Expand All @@ -31,8 +29,6 @@ import AnalyticsEvents
return .OlmKeysNotSentError
case .olmIndexError:
return .OlmIndexError
case .unexpected:
return .UnknownError
}
}
}
Expand Down
7 changes: 2 additions & 5 deletions Riot/Modules/Analytics/DecryptionFailureTracker.m
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,9 @@ - (void)reportUnableToDecryptErrorForEvent:(MXEvent *)event withRoomState:(MXRoo
reason = DecryptionFailureReasonOlmIndexError;
break;

case MXDecryptingErrorEncryptionNotEnabledCode:
case MXDecryptingErrorUnableToDecryptCode:
reason = DecryptionFailureReasonUnexpected;
break;

default:
// All other error codes will be tracked as `OlmUnspecifiedError` and will include `context` containing
// the actual error code and localized description
reason = DecryptionFailureReasonUnspecified;
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ extension __MXCallHangupReason {
switch self {
case .userHangup:
return .VoipUserHangup
case .userBusy:
// There is no dedicated analytics event for `userBusy` error
return .UnknownError
case .inviteTimeout:
return .VoipInviteTimeout
case .iceFailed:
Expand All @@ -32,6 +35,9 @@ extension __MXCallHangupReason {
case .unknownError:
return .UnknownError
default:
MXLog.failure("Unknown or unhandled hangup reason", context: [
"reason": rawValue
])
return .UnknownError
}
}
Expand Down
21 changes: 4 additions & 17 deletions Riot/Utils/EventFormatter.m
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,8 @@ - (BOOL)session:(MXSession *)session updateRoomSummary:(MXRoomSummary *)summary
return [self session:session
updateRoomSummary:summary
withVoiceBroadcastInfoStateEvent:lastVoiceBroadcastInfoEvent
voiceBroadcastInfoStartedEvent:voiceBroadcastInfoStartedEvent roomState:roomState];
voiceBroadcastInfoStartedEvent:voiceBroadcastInfoStartedEvent
roomState:roomState];
}
}

Expand Down Expand Up @@ -624,22 +625,8 @@ - (MXEvent *)voiceBroadcastInfoStartedEventWithEvent:(MXEvent *)voiceBroadcastIn
}
else
{
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);

__block MXEvent *voiceBroadcastInfoStartedEvent;

[session eventWithEventId:voiceBroadcastInfo.voiceBroadcastId inRoom:roomId success:^(MXEvent *resultEvent) {
voiceBroadcastInfoStartedEvent = resultEvent;
dispatch_group_leave(group);
} failure:^(NSError *error) {
MXLogErrorDetails(@"[EventFormatter] Fetch eventWithEventId with error = %@", error.description);
dispatch_group_leave(group);
}];

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

return voiceBroadcastInfoStartedEvent;
// Search for the event only in the store to avoid network calls while updating the room summary (this a synchronous process and we cannot delay it).
return [mxSession.store eventWithEventId:voiceBroadcastInfo.voiceBroadcastId inRoom:roomId];
}
}

Expand Down
21 changes: 13 additions & 8 deletions RiotSwiftUI/Modules/Common/Avatar/View/AvatarImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ struct AvatarImage: View {
var displayName: String?
var size: AvatarSize

@State private var avatar: AvatarViewState = .empty

var body: some View {
Group {
switch viewModel.viewState {
switch avatar {
case .empty:
ProgressView()
case .placeholder(let firstCharacter, let colorIndex):
Expand All @@ -42,13 +44,16 @@ struct AvatarImage: View {
.frame(maxWidth: CGFloat(size.rawValue), maxHeight: CGFloat(size.rawValue))
.clipShape(Circle())
.onAppear {
viewModel.loadAvatar(
mxContentUri: mxContentUri,
matrixItemId: matrixItemId,
displayName: displayName,
colorCount: theme.colors.namesAndAvatars.count,
avatarSize: size
)
avatar = viewModel.placeholderAvatar(matrixItemId: matrixItemId,
displayName: displayName,
colorCount: theme.colors.namesAndAvatars.count)
viewModel.loadAvatar(mxContentUri: mxContentUri,
matrixItemId: matrixItemId,
displayName: displayName,
colorCount: theme.colors.namesAndAvatars.count,
avatarSize: size ) { newState in
avatar = newState
}
}
}
}
Expand Down
40 changes: 23 additions & 17 deletions RiotSwiftUI/Modules/Common/Avatar/View/SpaceAvatarImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ struct SpaceAvatarImage: View {
var displayName: String?
var size: AvatarSize

@State private var avatar: AvatarViewState = .empty

var body: some View {
Group {
switch viewModel.viewState {
switch avatar {
case .empty:
ProgressView()
case .placeholder(let firstCharacter, let colorIndex):
Expand All @@ -48,23 +50,27 @@ struct SpaceAvatarImage: View {
.clipShape(RoundedRectangle(cornerRadius: 8))
}
}
.onChange(of: displayName, perform: { value in
viewModel.loadAvatar(
mxContentUri: mxContentUri,
matrixItemId: matrixItemId,
displayName: value,
colorCount: theme.colors.namesAndAvatars.count,
avatarSize: size
)
})
.onChange(of: displayName) { value in
guard case .placeholder = avatar else { return }
viewModel.loadAvatar(mxContentUri: mxContentUri,
matrixItemId: matrixItemId,
displayName: value,
colorCount: theme.colors.namesAndAvatars.count,
avatarSize: size) { newState in
avatar = newState
}
}
.onAppear {
viewModel.loadAvatar(
mxContentUri: mxContentUri,
matrixItemId: matrixItemId,
displayName: displayName,
colorCount: theme.colors.namesAndAvatars.count,
avatarSize: size
)
avatar = viewModel.placeholderAvatar(matrixItemId: matrixItemId,
displayName: displayName,
colorCount: theme.colors.namesAndAvatars.count)
viewModel.loadAvatar(mxContentUri: mxContentUri,
matrixItemId: matrixItemId,
displayName: displayName,
colorCount: theme.colors.namesAndAvatars.count,
avatarSize: size) { newState in
avatar = newState
}
}
}
}
Expand Down
25 changes: 15 additions & 10 deletions RiotSwiftUI/Modules/Common/Avatar/ViewModel/AvatarViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,22 @@ import Foundation
final class AvatarViewModel: ObservableObject {
private let avatarService: AvatarServiceProtocol

@Published private(set) var viewState = AvatarViewState.empty

init(avatarService: AvatarServiceProtocol) {
self.avatarService = avatarService
}

private var cancellables = Set<AnyCancellable>()

func placeholderAvatar(matrixItemId: String,
displayName: String?,
colorCount: Int) -> AvatarViewState {
let placeholderViewModel = PlaceholderAvatarViewModel(displayName: displayName,
matrixItemId: matrixItemId,
colorCount: colorCount)

return .placeholder(placeholderViewModel.firstCharacterCapitalized, placeholderViewModel.stableColorIndex)
}

/// Load an avatar
/// - Parameters:
/// - mxContentUri: The matrix content URI of the avatar.
Expand All @@ -41,23 +49,20 @@ final class AvatarViewModel: ObservableObject {
matrixItemId: String,
displayName: String?,
colorCount: Int,
avatarSize: AvatarSize) {
let placeholderViewModel = PlaceholderAvatarViewModel(displayName: displayName,
matrixItemId: matrixItemId,
colorCount: colorCount)

viewState = .placeholder(placeholderViewModel.firstCharacterCapitalized, placeholderViewModel.stableColorIndex)

avatarSize: AvatarSize,
avatarCompletion: @escaping (AvatarViewState) -> Void) {
guard let mxContentUri = mxContentUri, mxContentUri.count > 0 else {
avatarCompletion(placeholderAvatar(matrixItemId: matrixItemId, displayName: displayName, colorCount: colorCount))
return
}

avatarService.avatarImage(mxContentUri: mxContentUri, avatarSize: avatarSize)
.sink { completion in
guard case let .failure(error) = completion else { return }
UILog.error("[AvatarService] Failed to retrieve avatar", context: error)
// No need to call the completion, there's nothing we can do and the error is logged.
} receiveValue: { image in
self.viewState = .avatar(image)
avatarCompletion(.avatar(image))
}
.store(in: &cancellables)
}
Expand Down

0 comments on commit 78a4272

Please sign in to comment.