Skip to content

Commit

Permalink
Merge branch 'develop' into doug/room-list-previews
Browse files Browse the repository at this point in the history
  • Loading branch information
pixlwave committed Jun 29, 2023
2 parents ad4c5ea + 98cec56 commit f3ecf63
Show file tree
Hide file tree
Showing 20 changed files with 357 additions and 51 deletions.
25 changes: 25 additions & 0 deletions ElementX.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
368C8758FCD079E6AAA18C2C /* NoticeRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */; };
36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */; };
36AD4DD4C798E22584ED3200 /* Version in Frameworks */ = {isa = PBXBuildFile; productRef = A05AF81DDD14AD58CB0E1B9B /* Version */; };
36CD6E11B37396E14F032CB6 /* Flow in Frameworks */ = {isa = PBXBuildFile; productRef = 4D7E6BFC89715FC3CF0349D0 /* Flow */; };
37D789F24199B32E3FD1AA7B /* FileRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 216F0DDC98F2A2C162D09C28 /* FileRoomTimelineItemContent.swift */; };
38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */; };
38896D54D6D675534E606195 /* RoomTimelineControllerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */; };
Expand Down Expand Up @@ -213,6 +214,7 @@
520EEDAFBC778AB0B41F2F53 /* ClientMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE6170EFE6A161B0A68AB61 /* ClientMock.swift */; };
5375902175B2FEA2949D7D74 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */; };
53A55748D5F587C9061F98BF /* ServerConfigurationScreenViewStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277C20CDD5B64510401B6D0D /* ServerConfigurationScreenViewStateTests.swift */; };
53C1E7F6A7D6409D89F36ED7 /* AggregatedReactionMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69CB8242D69B7E4D0B32E18D /* AggregatedReactionMock.swift */; };
53DEF39F0C4DE02E3FC56D91 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 800631D7250B7F93195035F1 /* KeychainAccess */; };
53F1196F9C69512306A2693F /* TextRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28C19F54A0C4FC9AB7ABD583 /* TextRoomTimelineItemContent.swift */; };
5455147CAC63F71E48F7D699 /* NSELogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3D455BC2423D911A62ACFB2 /* NSELogger.swift */; };
Expand Down Expand Up @@ -383,6 +385,7 @@
8EF63DDDC1B54F122070B04D /* ReadMarkerRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6311F21F911E23BE4DF51B4 /* ReadMarkerRoomTimelineView.swift */; };
8F2FAA98457750D9D664136F /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = 4278261E147DB2DE5CFB7FC5 /* PostHog */; };
90733645AE76FB33DAD28C2B /* URLSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE40D4A5DD857AC16EED945A /* URLSession.swift */; };
9095B9E40DB5CF8BA26CE0D8 /* ReactionsSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 153726EDCE1ACBB3D466A916 /* ReactionsSummaryView.swift */; };
90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; };
90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; };
91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; };
Expand Down Expand Up @@ -818,6 +821,7 @@
1423AB065857FA546444DB15 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = "<group>"; };
142808B69851451AC32A2CEA /* RoomSummaryDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryDetails.swift; sourceTree = "<group>"; };
1454CF3AABD242F55C8A2615 /* InviteUsersScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenModels.swift; sourceTree = "<group>"; };
153726EDCE1ACBB3D466A916 /* ReactionsSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionsSummaryView.swift; sourceTree = "<group>"; };
15A657D96779D1DEB8EF1327 /* CreateRoomViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomViewModel.swift; sourceTree = "<group>"; };
16037EE9E9A52AF37B7818E3 /* AnalyticsSettingsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenUITests.swift; sourceTree = "<group>"; };
16D09C79746BDCD9173EB3A7 /* RoomDetailsEditScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenModels.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1029,6 +1033,7 @@
69219A908D7C22E6EE6689AE /* UserNotificationCenterSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationCenterSpy.swift; sourceTree = "<group>"; };
693E16574C6F7F9FA1015A8C /* Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Search.swift; sourceTree = "<group>"; };
69B63F817FE305548DB4B512 /* RoomMembersListViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListViewModelTests.swift; sourceTree = "<group>"; };
69CB8242D69B7E4D0B32E18D /* AggregatedReactionMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AggregatedReactionMock.swift; sourceTree = "<group>"; };
69D42EE0102D2857933625DD /* CreateRoomViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomViewModelTests.swift; sourceTree = "<group>"; };
6A4C9547BBFEEF30AA11329B /* TimelineItemStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemStatusView.swift; sourceTree = "<group>"; };
6A580295A56B55A856CC4084 /* InfoPlistReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoPlistReader.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1482,6 +1487,7 @@
754602A7B2AAD443C4228ED4 /* Sentry in Frameworks */,
B0CB16349B96262AA65A04AF /* URLRouting in Frameworks */,
36AD4DD4C798E22584ED3200 /* Version in Frameworks */,
36CD6E11B37396E14F032CB6 /* Flow in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -1766,6 +1772,7 @@
31CE4DA53232AA534057F912 /* Mocks */ = {
isa = PBXGroup;
children = (
69CB8242D69B7E4D0B32E18D /* AggregatedReactionMock.swift */,
36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */,
1ABDE6F66532CBEB0E016F94 /* RoomProxyMock.swift */,
248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */,
Expand Down Expand Up @@ -3134,6 +3141,7 @@
CCD48459CA34A1928EC7A26A /* Supplementary */ = {
isa = PBXGroup;
children = (
153726EDCE1ACBB3D466A916 /* ReactionsSummaryView.swift */,
D5AC06FC11B6638F7BF1670E /* TimelineDeliveryStatusView.swift */,
6A4C9547BBFEEF30AA11329B /* TimelineItemStatusView.swift */,
351E89CE2ED9B73C5CC47955 /* TimelineReactionsView.swift */,
Expand Down Expand Up @@ -3530,6 +3538,7 @@
7731767AE437BA3BD2CC14A8 /* Sentry */,
E9BAB8A793FE3B54CDD47102 /* URLRouting */,
A05AF81DDD14AD58CB0E1B9B /* Version */,
4D7E6BFC89715FC3CF0349D0 /* Flow */,
);
productName = ElementX;
productReference = 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */;
Expand Down Expand Up @@ -3643,6 +3652,7 @@
9754C4B03F6255F67FC15E52 /* XCRemoteSwiftPackageReference "compound-ios" */,
C13F55E4518415CB4C278E73 /* XCRemoteSwiftPackageReference "DTCoreText" */,
D5F7D47BBAAE0CF1DDEB3034 /* XCRemoteSwiftPackageReference "DeviceKit" */,
65398401562A467FD2FDCF20 /* XCRemoteSwiftPackageReference "SwiftUI-Flow" */,
701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */,
9A472EE0218FE7DCF5283429 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */,
395DE6AE429B7ACC7C7FE31D /* XCRemoteSwiftPackageReference "KZFileWatchers" */,
Expand Down Expand Up @@ -3964,6 +3974,7 @@
files = (
41F553349AF44567184822D8 /* APNSPayload.swift in Sources */,
70394ECD2DCC70741538620D /* AccessibilityIdentifiers.swift in Sources */,
53C1E7F6A7D6409D89F36ED7 /* AggregatedReactionMock.swift in Sources */,
4219391CD2351E410554B3E8 /* AggregratedReaction.swift in Sources */,
64D05250CEDE8B604119F6E6 /* Alert.swift in Sources */,
39929D29B265C3F6606047DE /* AlignedScrollView.swift in Sources */,
Expand Down Expand Up @@ -4225,6 +4236,7 @@
1BA04D05EBC6646958B1BE60 /* PlaceholderScreenCoordinator.swift in Sources */,
DF504B10A4918F971A57BEF2 /* PostHogAnalyticsClient.swift in Sources */,
2835FD52F3F618D07F799B3D /* Publisher.swift in Sources */,
9095B9E40DB5CF8BA26CE0D8 /* ReactionsSummaryView.swift in Sources */,
743790BF6A5B0577EA74AF14 /* ReadMarkerRoomTimelineItem.swift in Sources */,
8EF63DDDC1B54F122070B04D /* ReadMarkerRoomTimelineView.swift in Sources */,
91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */,
Expand Down Expand Up @@ -5058,6 +5070,14 @@
minimumVersion = 4.2.0;
};
};
65398401562A467FD2FDCF20 /* XCRemoteSwiftPackageReference "SwiftUI-Flow" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/tevelee/SwiftUI-Flow";
requirement = {
kind = upToNextMinorVersion;
minimumVersion = 1.2.0;
};
};
6582B5AF3F104B0F7E031E7D /* XCRemoteSwiftPackageReference "SwiftState" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/ReactKit/SwiftState";
Expand Down Expand Up @@ -5256,6 +5276,11 @@
package = 96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */;
productName = PostHog;
};
4D7E6BFC89715FC3CF0349D0 /* Flow */ = {
isa = XCSwiftPackageProductDependency;
package = 65398401562A467FD2FDCF20 /* XCRemoteSwiftPackageReference "SwiftUI-Flow" */;
productName = Flow;
};
50009897F60FAE7D63EF5E5B /* Kingfisher */ = {
isa = XCSwiftPackageProductDependency;
package = D283517192CAC3E2E6920765 /* XCRemoteSwiftPackageReference "Kingfisher" */;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,15 @@
"version" : "1.0.0"
}
},
{
"identity" : "swift-argument-parser",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser",
"state" : {
"revision" : "fee6933f37fde9a5e12a1e4aeaa93fe60116ff2a",
"version" : "1.2.2"
}
},
{
"identity" : "swift-case-paths",
"kind" : "remoteSourceControl",
Expand Down Expand Up @@ -205,6 +214,15 @@
"version" : "6.0.1"
}
},
{
"identity" : "swiftui-flow",
"kind" : "remoteSourceControl",
"location" : "https://github.com/tevelee/SwiftUI-Flow",
"state" : {
"revision" : "d592b610a92869b74ede8ee4c0435a29219be9d8",
"version" : "1.2.0"
}
},
{
"identity" : "swiftui-introspect",
"kind" : "remoteSourceControl",
Expand Down
56 changes: 56 additions & 0 deletions ElementX/Sources/Mocks/AggregatedReactionMock.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// Copyright 2023 New Vector Ltd
//
// 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

extension AggregatedReaction {
private static func mockIds(_ count: Int) -> [String] {
Array(1...count).map {
"@user\($0):matrix.org"
}
}

private static var alice: String {
RoomMemberProxyMock.mockAlice.userID
}

static var mockThumbsUpHighlighted: AggregatedReaction {
AggregatedReaction(accountOwnerID: alice, key: "👍", senders: [alice] + mockIds(4))
}

static var mockClap: AggregatedReaction {
AggregatedReaction(accountOwnerID: alice, key: "👏", senders: mockIds(1))
}

static var mockParty: AggregatedReaction {
AggregatedReaction(accountOwnerID: alice, key: "🎉", senders: mockIds(20))
}

static var mockReactions: [AggregatedReaction] {
[
AggregatedReaction(accountOwnerID: alice, key: "😅", senders: [alice]),
AggregatedReaction(accountOwnerID: alice, key: "🤷‍♂️", senders: mockIds(1)),
AggregatedReaction(accountOwnerID: alice, key: "🎨", senders: [alice] + mockIds(5)),
AggregatedReaction(accountOwnerID: alice, key: "🎉", senders: mockIds(8)),
AggregatedReaction(accountOwnerID: alice, key: "🤯", senders: [alice] + mockIds(14)),
AggregatedReaction(accountOwnerID: alice, key: "🫣", senders: mockIds(1)),
AggregatedReaction(accountOwnerID: alice, key: "🚀", senders: [alice] + mockIds(3)),
AggregatedReaction(accountOwnerID: alice, key: "😇", senders: mockIds(2)),
AggregatedReaction(accountOwnerID: alice, key: "🤭", senders: [alice] + mockIds(8)),
AggregatedReaction(accountOwnerID: alice, key: "🫤", senders: mockIds(10))
]
}
}
13 changes: 13 additions & 0 deletions ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ enum RoomScreenViewAction {

case handlePasteOrDrop(provider: NSItemProvider)
case tappedOnUser(userID: String)

case reactionSummary(itemID: String, key: String)

case retrySend(transactionID: String?)
case cancelSend(transactionID: String?)
Expand Down Expand Up @@ -126,6 +128,8 @@ struct RoomScreenViewStateBindings {
var actionMenuInfo: TimelineItemActionMenuInfo?

var sendFailedConfirmationDialogInfo: SendFailedConfirmationDialogInfo?

var reactionSummaryInfo: ReactionSummaryInfo?
}

struct TimelineItemActionMenuInfo: Identifiable, Equatable {
Expand All @@ -146,6 +150,15 @@ struct SendFailedConfirmationDialogInfo: ConfirmationDialogProtocol {
let transactionID: String?
}

struct ReactionSummaryInfo: Identifiable {
let reactions: [AggregatedReaction]
let selectedKey: String

var id: String {
selectedKey
}
}

enum RoomScreenErrorType: Hashable {
/// A specific error message shown in an alert.
case alert(String)
Expand Down
13 changes: 13 additions & 0 deletions ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
case .displayEmojiPicker(let itemID):
guard let item = state.items.first(where: { $0.id == itemID }), item.isReactable else { return }
callback?(.displayEmojiPicker(itemID: itemID))
case .reactionSummary(let itemId, let key):
showReactionSummary(for: itemId, selectedKey: key)
case .retrySend(let transactionID):
Task { await handleRetrySend(transactionID: transactionID) }
case .cancelSend(let transactionID):
Expand Down Expand Up @@ -619,6 +621,17 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
}
}
}

// MARK: - Reaction summary

private func showReactionSummary(for itemID: String, selectedKey: String) {
guard let timelineItem = timelineController.timelineItems.first(where: { $0.id == itemID }),
let eventTimelineItem = timelineItem as? EventBasedTimelineItemProtocol else {
return
}

state.bindings.reactionSummaryInfo = .init(reactions: eventTimelineItem.properties.reactions, selectedKey: selectedKey)
}
}

private extension RoomProxyProtocol {
Expand Down
5 changes: 4 additions & 1 deletion ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import SwiftUI

struct RoomScreen: View {
@ObservedObject var context: RoomScreenViewModel.Context
@State private var showReactionsMenuForItemId = ""
@State private var dragOver = false

private let attachmentButtonPadding = 10.0
Expand Down Expand Up @@ -50,6 +49,10 @@ struct RoomScreen: View {
.environmentObject(context)
}
}
.sheet(item: $context.reactionSummaryInfo) {
ReactionsSummaryView(reactions: $0.reactions, members: context.viewState.members, imageProvider: context.imageProvider, selectedReactionKey: $0.selectedKey)
.edgesIgnoringSafeArea([.bottom])
}
.interactiveQuickLook(item: $context.mediaPreviewItem)
.track(screen: .room)
.task(id: context.viewState.roomId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import SwiftUI
struct TimelineItemBubbledStylerView<Content: View>: View {
@EnvironmentObject private var context: RoomScreenViewModel.Context
@Environment(\.timelineGroupStyle) private var timelineGroupStyle
@Environment(\.layoutDirection) var layoutDirection: LayoutDirection

let timelineItem: EventBasedTimelineItemProtocol
@ViewBuilder let content: () -> Content
Expand All @@ -31,7 +32,12 @@ struct TimelineItemBubbledStylerView<Content: View>: View {

private var isTextItem: Bool { timelineItem is TextBasedRoomTimelineItem }
private var isEncryptedOneToOneRoom: Bool { context.viewState.isEncryptedOneToOneRoom }


var reactionsLayoutDirection: LayoutDirection {
guard timelineItem.isOutgoing else { return layoutDirection }
return layoutDirection == .leftToRight ? .rightToLeft : .leftToRight
}

var body: some View {
ZStack(alignment: .trailingFirstTextBaseline) {
VStack(alignment: alignment, spacing: -12) {
Expand Down Expand Up @@ -92,10 +98,12 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
.accessibilityElement(children: .combine)

if !timelineItem.properties.reactions.isEmpty {
TimelineReactionsView(reactions: timelineItem.properties.reactions,
alignment: alignment) { key in
TimelineReactionsView(reactions: timelineItem.properties.reactions) { key in
context.send(viewAction: .toggleReaction(key: key, eventID: timelineItem.id))
} showReactionSummary: { key in
context.send(viewAction: .reactionSummary(itemID: timelineItem.id, key: key))
}
.environment(\.layoutDirection, reactionsLayoutDirection)
// Workaround to stop the message long press stealing the touch from the reaction buttons
.onTapGesture { }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,10 @@ struct TimelineItemPlainStylerView<Content: View>: View {
}

if !timelineItem.properties.reactions.isEmpty {
TimelineReactionsView(reactions: timelineItem.properties.reactions,
alignment: .leading) { key in
TimelineReactionsView(reactions: timelineItem.properties.reactions) { key in
context.send(viewAction: .toggleReaction(key: key, eventID: timelineItem.id))
} showReactionSummary: { key in
context.send(viewAction: .reactionSummary(itemID: timelineItem.id, key: key))
}
// Workaround to stop the message long press stealing the touch from the reaction buttons
.onTapGesture { }
Expand Down

0 comments on commit f3ecf63

Please sign in to comment.