mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Makes the MockTimelineController configurable with incoming items and pagination responses.
This commit is contained in:
@@ -208,6 +208,7 @@
|
|||||||
6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFF7BF82A950B91BC5469E91 /* ViewFrameReader.swift */; };
|
6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFF7BF82A950B91BC5469E91 /* ViewFrameReader.swift */; };
|
||||||
7002C55A4C917F3715765127 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C888BCD78E2A55DCE364F160 /* MediaProviderProtocol.swift */; };
|
7002C55A4C917F3715765127 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C888BCD78E2A55DCE364F160 /* MediaProviderProtocol.swift */; };
|
||||||
702694459B649B9D3A3C34F8 /* TimelineTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9212AE02CBDD692C56A879F /* TimelineTableViewController.swift */; };
|
702694459B649B9D3A3C34F8 /* TimelineTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9212AE02CBDD692C56A879F /* TimelineTableViewController.swift */; };
|
||||||
|
70558528EF68CAAEF09972D5 /* RoomTimelineItemFixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */; };
|
||||||
706F79A39BDB32F592B8C2C7 /* UIKitBackgroundTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92FCD9116ADDE820E4E30F92 /* UIKitBackgroundTask.swift */; };
|
706F79A39BDB32F592B8C2C7 /* UIKitBackgroundTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92FCD9116ADDE820E4E30F92 /* UIKitBackgroundTask.swift */; };
|
||||||
7096FA3AC218D914E88BFB70 /* AggregratedReaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = F15BE37BE2FB86E00C8D150A /* AggregratedReaction.swift */; };
|
7096FA3AC218D914E88BFB70 /* AggregratedReaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = F15BE37BE2FB86E00C8D150A /* AggregratedReaction.swift */; };
|
||||||
719E7AAD1F8E68F68F30FECD /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = A40C19719687984FD9478FBE /* Task.swift */; };
|
719E7AAD1F8E68F68F30FECD /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = A40C19719687984FD9478FBE /* Task.swift */; };
|
||||||
@@ -964,6 +965,7 @@
|
|||||||
E6281B199D8A8F0892490C2E /* OnboardingCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingCoordinator.swift; sourceTree = "<group>"; };
|
E6281B199D8A8F0892490C2E /* OnboardingCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingCoordinator.swift; sourceTree = "<group>"; };
|
||||||
E8294DB9E95C0C0630418466 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
|
E8294DB9E95C0C0630418466 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIFont+AttributedStringBuilder.m"; sourceTree = "<group>"; };
|
E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIFont+AttributedStringBuilder.m"; sourceTree = "<group>"; };
|
||||||
|
E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFixtures.swift; sourceTree = "<group>"; };
|
||||||
E9D059BFE329BE09B6D96A9F /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ro; path = ro.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
E9D059BFE329BE09B6D96A9F /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ro; path = ro.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilderTests.swift; sourceTree = "<group>"; };
|
EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilderTests.swift; sourceTree = "<group>"; };
|
||||||
EBE5502760CF6CA2D7201883 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ja; path = ja.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
EBE5502760CF6CA2D7201883 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ja; path = ja.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
@@ -1295,6 +1297,14 @@
|
|||||||
path = Helpers;
|
path = Helpers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
3EA31CC7012EA2A5653DAFC9 /* Fixtures */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */,
|
||||||
|
);
|
||||||
|
path = Fixtures;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
3F38EAC92E2281990E65DAF2 /* OnboardingScreen */ = {
|
3F38EAC92E2281990E65DAF2 /* OnboardingScreen */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -2293,6 +2303,7 @@
|
|||||||
66F2402D738694F98729A441 /* RoomTimelineProvider.swift */,
|
66F2402D738694F98729A441 /* RoomTimelineProvider.swift */,
|
||||||
095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */,
|
095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */,
|
||||||
2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */,
|
2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */,
|
||||||
|
3EA31CC7012EA2A5653DAFC9 /* Fixtures */,
|
||||||
5A7A7D6D373D411C8C48B881 /* TimeLineItemContent */,
|
5A7A7D6D373D411C8C48B881 /* TimeLineItemContent */,
|
||||||
95BE1C7CB2C80344FF0BE724 /* TimelineItems */,
|
95BE1C7CB2C80344FF0BE724 /* TimelineItems */,
|
||||||
);
|
);
|
||||||
@@ -2973,6 +2984,7 @@
|
|||||||
9B8DE1D424E37581C7D99CCC /* RoomTimelineControllerProtocol.swift in Sources */,
|
9B8DE1D424E37581C7D99CCC /* RoomTimelineControllerProtocol.swift in Sources */,
|
||||||
4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */,
|
4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */,
|
||||||
13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */,
|
13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */,
|
||||||
|
70558528EF68CAAEF09972D5 /* RoomTimelineItemFixtures.swift in Sources */,
|
||||||
C8E82786DE1B6A400DA9BA25 /* RoomTimelineItemProperties.swift in Sources */,
|
C8E82786DE1B6A400DA9BA25 /* RoomTimelineItemProperties.swift in Sources */,
|
||||||
1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */,
|
1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */,
|
||||||
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */,
|
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */,
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ struct TimelineView: UIViewControllerRepresentable {
|
|||||||
timelineStyle: timelineStyle,
|
timelineStyle: timelineStyle,
|
||||||
scrollToBottomButtonVisible: $viewModelContext.scrollToBottomButtonVisible,
|
scrollToBottomButtonVisible: $viewModelContext.scrollToBottomButtonVisible,
|
||||||
scrollToBottomPublisher: viewModelContext.viewState.scrollToBottomPublisher)
|
scrollToBottomPublisher: viewModelContext.viewState.scrollToBottomPublisher)
|
||||||
viewModelContext.send(viewAction: .paginateBackwards)
|
|
||||||
return tableViewController
|
return tableViewController
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +45,10 @@ struct TimelineView: UIViewControllerRepresentable {
|
|||||||
|
|
||||||
init(viewModelContext: RoomScreenViewModel.Context) {
|
init(viewModelContext: RoomScreenViewModel.Context) {
|
||||||
context = viewModelContext
|
context = viewModelContext
|
||||||
|
|
||||||
|
if viewModelContext.viewState.items.isEmpty {
|
||||||
|
viewModelContext.send(viewAction: .paginateBackwards)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates the specified table view's properties from the current view state.
|
/// Updates the specified table view's properties from the current view state.
|
||||||
|
|||||||
@@ -0,0 +1,222 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 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
|
||||||
|
|
||||||
|
enum RoomTimelineItemFixtures {
|
||||||
|
/// The default timeline items used in Xcode previews etc.
|
||||||
|
static var `default`: [RoomTimelineItemProtocol] = [
|
||||||
|
SeparatorRoomTimelineItem(id: UUID().uuidString,
|
||||||
|
text: "Yesterday"),
|
||||||
|
TextRoomTimelineItem(id: UUID().uuidString,
|
||||||
|
text: "That looks so good!",
|
||||||
|
timestamp: "10:10 AM",
|
||||||
|
inGroupState: .single,
|
||||||
|
isOutgoing: false,
|
||||||
|
isEditable: false,
|
||||||
|
senderId: "",
|
||||||
|
senderDisplayName: "Jacob",
|
||||||
|
properties: RoomTimelineItemProperties(isEdited: true)),
|
||||||
|
TextRoomTimelineItem(id: UUID().uuidString,
|
||||||
|
text: "Let’s get lunch soon! New salad place opened up 🥗. When are y’all free? 🤗",
|
||||||
|
timestamp: "10:11 AM",
|
||||||
|
inGroupState: .beginning,
|
||||||
|
isOutgoing: false,
|
||||||
|
isEditable: false,
|
||||||
|
senderId: "",
|
||||||
|
senderDisplayName: "Helena",
|
||||||
|
properties: RoomTimelineItemProperties(reactions: [
|
||||||
|
AggregatedReaction(key: "🙌", count: 1, isHighlighted: true)
|
||||||
|
])),
|
||||||
|
TextRoomTimelineItem(id: UUID().uuidString,
|
||||||
|
text: "I can be around on Wednesday. How about some 🌮 instead? Like https://www.tortilla.co.uk/",
|
||||||
|
timestamp: "10:11 AM",
|
||||||
|
inGroupState: .end,
|
||||||
|
isOutgoing: false,
|
||||||
|
isEditable: false,
|
||||||
|
senderId: "",
|
||||||
|
senderDisplayName: "Helena",
|
||||||
|
properties: RoomTimelineItemProperties(reactions: [
|
||||||
|
AggregatedReaction(key: "🙏", count: 1, isHighlighted: false),
|
||||||
|
AggregatedReaction(key: "🙌", count: 2, isHighlighted: true)
|
||||||
|
])),
|
||||||
|
SeparatorRoomTimelineItem(id: UUID().uuidString,
|
||||||
|
text: "Today"),
|
||||||
|
TextRoomTimelineItem(id: UUID().uuidString,
|
||||||
|
text: "Wow, cool. Ok, lets go the usual place tomorrow?! Is that too soon? Here’s the menu, let me know what you want it’s on me!",
|
||||||
|
timestamp: "5 PM",
|
||||||
|
inGroupState: .single,
|
||||||
|
isOutgoing: false,
|
||||||
|
isEditable: false,
|
||||||
|
senderId: "",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(id: UUID().uuidString,
|
||||||
|
text: "And John's speech was amazing!",
|
||||||
|
timestamp: "5 PM",
|
||||||
|
inGroupState: .beginning,
|
||||||
|
isOutgoing: true,
|
||||||
|
isEditable: true,
|
||||||
|
senderId: "",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(id: UUID().uuidString,
|
||||||
|
text: "New home office set up!",
|
||||||
|
timestamp: "5 PM",
|
||||||
|
inGroupState: .end,
|
||||||
|
isOutgoing: true,
|
||||||
|
isEditable: true,
|
||||||
|
senderId: "",
|
||||||
|
senderDisplayName: "Bob",
|
||||||
|
properties: RoomTimelineItemProperties(reactions: [
|
||||||
|
AggregatedReaction(key: "🙏", count: 1, isHighlighted: false),
|
||||||
|
AggregatedReaction(key: "😁", count: 3, isHighlighted: false)
|
||||||
|
])),
|
||||||
|
TextRoomTimelineItem(id: UUID().uuidString,
|
||||||
|
text: "",
|
||||||
|
attributedComponents: [
|
||||||
|
AttributedStringBuilderComponent(attributedString: "Hol' up", isBlockquote: false),
|
||||||
|
AttributedStringBuilderComponent(attributedString: "New home office set up!", isBlockquote: true),
|
||||||
|
AttributedStringBuilderComponent(attributedString: "That's amazing! Congrats 🥳", isBlockquote: false)
|
||||||
|
],
|
||||||
|
timestamp: "5 PM",
|
||||||
|
inGroupState: .single,
|
||||||
|
isOutgoing: false,
|
||||||
|
isEditable: false,
|
||||||
|
senderId: "",
|
||||||
|
senderDisplayName: "Helena")
|
||||||
|
]
|
||||||
|
|
||||||
|
/// A small chunk of events, containing 2 text items.
|
||||||
|
static var smallChunk: [RoomTimelineItemProtocol] {
|
||||||
|
[TextRoomTimelineItem(text: "Hey there 👋",
|
||||||
|
inGroupState: .beginning,
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "How are you?",
|
||||||
|
inGroupState: .end,
|
||||||
|
senderDisplayName: "Alice")]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A chunk of events that contains a single text item.
|
||||||
|
static var singleMessageChunk: [RoomTimelineItemProtocol] {
|
||||||
|
[TextRoomTimelineItem(text: "Tap tap tap 🎙️. Is this thing on?",
|
||||||
|
inGroupState: .single,
|
||||||
|
senderDisplayName: "Helena")]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A single text item.
|
||||||
|
static var incomingMessage: RoomTimelineItemProtocol {
|
||||||
|
TextRoomTimelineItem(text: "Hello, World!",
|
||||||
|
inGroupState: .single,
|
||||||
|
senderDisplayName: "Bob")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A large chunk of events, containing 40 text items which should fill an iPad
|
||||||
|
/// with enough items so that it won't perform another back pagination.
|
||||||
|
static var largeChunk: [RoomTimelineItemProtocol] {
|
||||||
|
[TextRoomTimelineItem(text: "Bacon ipsum dolor amet commodo incididunt ribeye dolore cupidatat short ribs.",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(text: "Labore ipsum jowl meatloaf adipisicing ham leberkas.",
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "Tongue culpa dolor, short ribs doner cillum do rump id nulla mollit.",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(text: "Capicola laborum aute porchetta, kevin ut ut bacon swine kielbasa beef rump ipsum.",
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "Leberkas beef ad salami flank laborum ex veniam excepteur picanha occaecat burgdoggen.",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(text: "Magna leberkas nostrud laboris, biltong in tongue nulla et id drumstick brisket.",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(text: "Landjaeger adipisicing spare ribs sunt pig voluptate beef ribs venison ut meatloaf nulla beef sed.",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(text: "Bacon chicken excepteur, filet mignon pastrami meatball ribeye sunt sausage.",
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "Ham et dolore, nisi adipisicing kielbasa andouille ribeye enim chicken.",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(text: "Ribeye prosciutto aliquip tail dolore.",
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "Salami culpa exercitation ea non rump consectetur ipsum boudin irure jerky spare ribs duis leberkas pastrami.",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(text: "Andouille shankle magna pig corned beef strip steak ex landjaeger sed chicken drumstick.",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(text: "Deserunt ea esse quis bresaola, ham hock sirloin spare ribs porchetta dolore ham nisi est.",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(text: "Consectetur nulla laboris, rump minim tempor turducken sunt tongue in.",
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "Ea ut laboris eu spare ribs occaecat esse et shankle chicken.",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(text: "Frankfurter brisket eu, landjaeger ea ham hamburger rump eiusmod pastrami cow.",
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "Qui prosciutto sed, officia occaecat drumstick non veniam in elit chicken capicola buffalo beef ribs irure.",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(text: "In pork loin lorem, pariatur tail cupim voluptate chicken id eu pancetta esse pastrami.",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(text: "Excepteur minim ea est, jerky sirloin frankfurter nisi dolor ball tip.",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(text: "Shank corned beef velit chislic, pork chop enim in chuck in excepteur fatback minim.",
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "Mollit minim ipsum in, in do doner ribeye cow jowl short loin sed.",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(text: "Meatloaf est hamburger, spare ribs pork belly officia dolor.",
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "Pancetta do aliqua picanha tempor.",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(text: "Ad pig incididunt doner pork chop flank velit capicola aliqua.",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(text: "Ullamco ex qui kevin meatball, leberkas hamburger venison.",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(text: "Capicola et esse, fatback porchetta filet mignon ham nulla salami shank.",
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "Boudin adipisicing pancetta chuck spare ribs beef ribs, in ut pork kevin.",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(text: "Adipisicing pig short loin hamburger nisi exercitation landjaeger pancetta picanha ex cupim beef ribs.",
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "Burgdoggen tri-tip eu elit consectetur, hamburger dolore commodo bacon capicola esse ex exercitation anim nostrud.",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(text: "Id burgdoggen bresaola pork.",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(text: "Pariatur meatloaf dolore tenderloin ea et proident strip steak velit nostrud pork loin laboris.",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(text: "Pork chop cupim pastrami, prosciutto chislic kevin tempor eu ut deserunt ut occaecat consectetur non.",
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "Aliquip kevin fugiat esse, adipisicing bresaola andouille biltong.",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(text: "Andouille est picanha, beef ribs boudin exercitation flank venison ea tongue landjaeger meatloaf velit.",
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "Boudin rump hamburger laborum adipisicing consectetur officia frankfurter shoulder quis biltong fugiat esse.",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(text: "Ham hock culpa corned beef cupim pastrami swine in.",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(text: "Boudin adipisicing pancetta chuck spare ribs beef ribs, in ut pork kevin.",
|
||||||
|
senderDisplayName: "Bob"),
|
||||||
|
TextRoomTimelineItem(text: "Aliquip meatball incididunt fatback, pork belly in jowl tri-tip commodo spare ribs.",
|
||||||
|
senderDisplayName: "Alice"),
|
||||||
|
TextRoomTimelineItem(text: "Excepteur rump tri-tip culpa in shankle esse ut.",
|
||||||
|
senderDisplayName: "Helena"),
|
||||||
|
TextRoomTimelineItem(text: "Pork buffalo mollit culpa strip steak in leberkas flank cow.",
|
||||||
|
senderDisplayName: "Alice")]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension TextRoomTimelineItem {
|
||||||
|
init(text: String, inGroupState: TimelineItemInGroupState = .single, senderDisplayName: String) {
|
||||||
|
self.init(id: UUID().uuidString,
|
||||||
|
text: text,
|
||||||
|
timestamp: "10:47 am",
|
||||||
|
inGroupState: inGroupState,
|
||||||
|
isOutgoing: senderDisplayName == "Alice",
|
||||||
|
isEditable: false,
|
||||||
|
senderId: "",
|
||||||
|
senderDisplayName: senderDisplayName)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,92 +18,54 @@ import Combine
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class MockRoomTimelineController: RoomTimelineControllerProtocol {
|
class MockRoomTimelineController: RoomTimelineControllerProtocol {
|
||||||
|
/// An array of timeline item arrays that will be inserted in order for each back pagination request.
|
||||||
|
var backPaginationResponses: [[RoomTimelineItemProtocol]] = []
|
||||||
|
/// The time delay added to each back pagination request.
|
||||||
|
var backPaginationDelay: Duration = .milliseconds(500)
|
||||||
|
|
||||||
|
/// An array of timeline items that will be appended in order when ``simulateIncomingItems()`` is called.
|
||||||
|
var incomingItems: [RoomTimelineItemProtocol] = []
|
||||||
|
/// The time delay between each incoming item.
|
||||||
|
var incomingDelay: Duration = .milliseconds(750)
|
||||||
|
|
||||||
let roomId = "MockRoomIdentifier"
|
let roomId = "MockRoomIdentifier"
|
||||||
|
|
||||||
let callbacks = PassthroughSubject<RoomTimelineControllerCallback, Never>()
|
let callbacks = PassthroughSubject<RoomTimelineControllerCallback, Never>()
|
||||||
|
|
||||||
var timelineItems: [RoomTimelineItemProtocol] = [
|
var timelineItems: [RoomTimelineItemProtocol] = RoomTimelineItemFixtures.default
|
||||||
SeparatorRoomTimelineItem(id: UUID().uuidString,
|
|
||||||
text: "Yesterday"),
|
func simulateIncomingItems() {
|
||||||
TextRoomTimelineItem(id: UUID().uuidString,
|
guard !incomingItems.isEmpty else { return }
|
||||||
text: "That looks so good!",
|
|
||||||
timestamp: "10:10 AM",
|
let incomingItem = incomingItems.removeFirst()
|
||||||
inGroupState: .single,
|
|
||||||
isOutgoing: false,
|
Task {
|
||||||
isEditable: false,
|
try await Task.sleep(for: incomingDelay)
|
||||||
senderId: "",
|
timelineItems.append(incomingItem)
|
||||||
senderDisplayName: "Jacob",
|
callbacks.send(.updatedTimelineItems)
|
||||||
properties: RoomTimelineItemProperties(isEdited: true)),
|
|
||||||
TextRoomTimelineItem(id: UUID().uuidString,
|
if !self.incomingItems.isEmpty {
|
||||||
text: "Let’s get lunch soon! New salad place opened up 🥗. When are y’all free? 🤗",
|
simulateIncomingItems()
|
||||||
timestamp: "10:11 AM",
|
}
|
||||||
inGroupState: .beginning,
|
}
|
||||||
isOutgoing: false,
|
}
|
||||||
isEditable: false,
|
|
||||||
senderId: "",
|
|
||||||
senderDisplayName: "Helena",
|
|
||||||
properties: RoomTimelineItemProperties(reactions: [
|
|
||||||
AggregatedReaction(key: "🙌", count: 1, isHighlighted: true)
|
|
||||||
])),
|
|
||||||
TextRoomTimelineItem(id: UUID().uuidString,
|
|
||||||
text: "I can be around on Wednesday. How about some 🌮 instead? Like https://www.tortilla.co.uk/",
|
|
||||||
timestamp: "10:11 AM",
|
|
||||||
inGroupState: .end,
|
|
||||||
isOutgoing: false,
|
|
||||||
isEditable: false,
|
|
||||||
senderId: "",
|
|
||||||
senderDisplayName: "Helena",
|
|
||||||
properties: RoomTimelineItemProperties(reactions: [
|
|
||||||
AggregatedReaction(key: "🙏", count: 1, isHighlighted: false),
|
|
||||||
AggregatedReaction(key: "🙌", count: 2, isHighlighted: true)
|
|
||||||
])),
|
|
||||||
SeparatorRoomTimelineItem(id: UUID().uuidString,
|
|
||||||
text: "Today"),
|
|
||||||
TextRoomTimelineItem(id: UUID().uuidString,
|
|
||||||
text: "Wow, cool. Ok, lets go the usual place tomorrow?! Is that too soon? Here’s the menu, let me know what you want it’s on me!",
|
|
||||||
timestamp: "5 PM",
|
|
||||||
inGroupState: .single,
|
|
||||||
isOutgoing: false,
|
|
||||||
isEditable: false,
|
|
||||||
senderId: "",
|
|
||||||
senderDisplayName: "Helena"),
|
|
||||||
TextRoomTimelineItem(id: UUID().uuidString,
|
|
||||||
text: "And John's speech was amazing!",
|
|
||||||
timestamp: "5 PM",
|
|
||||||
inGroupState: .beginning,
|
|
||||||
isOutgoing: true,
|
|
||||||
isEditable: true,
|
|
||||||
senderId: "",
|
|
||||||
senderDisplayName: "Bob"),
|
|
||||||
TextRoomTimelineItem(id: UUID().uuidString,
|
|
||||||
text: "New home office set up!",
|
|
||||||
timestamp: "5 PM",
|
|
||||||
inGroupState: .end,
|
|
||||||
isOutgoing: true,
|
|
||||||
isEditable: true,
|
|
||||||
senderId: "",
|
|
||||||
senderDisplayName: "Bob",
|
|
||||||
properties: RoomTimelineItemProperties(reactions: [
|
|
||||||
AggregatedReaction(key: "🙏", count: 1, isHighlighted: false),
|
|
||||||
AggregatedReaction(key: "😁", count: 3, isHighlighted: false)
|
|
||||||
])),
|
|
||||||
TextRoomTimelineItem(id: UUID().uuidString,
|
|
||||||
text: "",
|
|
||||||
attributedComponents: [
|
|
||||||
AttributedStringBuilderComponent(attributedString: "Hol' up", isBlockquote: false),
|
|
||||||
AttributedStringBuilderComponent(attributedString: "New home office set up!", isBlockquote: true),
|
|
||||||
AttributedStringBuilderComponent(attributedString: "That's amazing! Congrats 🥳", isBlockquote: false)
|
|
||||||
],
|
|
||||||
timestamp: "5 PM",
|
|
||||||
inGroupState: .single,
|
|
||||||
isOutgoing: false,
|
|
||||||
isEditable: false,
|
|
||||||
senderId: "",
|
|
||||||
senderDisplayName: "Helena")
|
|
||||||
]
|
|
||||||
|
|
||||||
func paginateBackwards(_ count: UInt) async -> Result<Void, RoomTimelineControllerError> {
|
func paginateBackwards(_ count: UInt) async -> Result<Void, RoomTimelineControllerError> {
|
||||||
.failure(.generic)
|
callbacks.send(.startedBackPaginating)
|
||||||
|
|
||||||
|
guard !backPaginationResponses.isEmpty else {
|
||||||
|
callbacks.send(.finishedBackPaginating)
|
||||||
|
return .failure(.generic)
|
||||||
|
}
|
||||||
|
|
||||||
|
let newItems = backPaginationResponses.removeFirst()
|
||||||
|
|
||||||
|
try? await Task.sleep(for: backPaginationDelay)
|
||||||
|
timelineItems.insert(contentsOf: newItems, at: 0)
|
||||||
|
callbacks.send(.updatedTimelineItems)
|
||||||
|
callbacks.send(.finishedBackPaginating)
|
||||||
|
|
||||||
|
return .success(())
|
||||||
}
|
}
|
||||||
|
|
||||||
func processItemAppearance(_ itemId: String) async { }
|
func processItemAppearance(_ itemId: String) async { }
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ enum UITestScreenIdentifier: String {
|
|||||||
case onboarding
|
case onboarding
|
||||||
case roomPlainNoAvatar
|
case roomPlainNoAvatar
|
||||||
case roomEncryptedWithAvatar
|
case roomEncryptedWithAvatar
|
||||||
|
case roomSmallTimeline
|
||||||
|
case roomSmallTimelineIncomingAndSmallPagination
|
||||||
|
case roomSmallTimelineLargePagination
|
||||||
case sessionVerification
|
case sessionVerification
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class UITestsAppCoordinator: AppCoordinatorProtocol {
|
|||||||
let notificationManager: NotificationManagerProtocol? = nil
|
let notificationManager: NotificationManagerProtocol? = nil
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
UIView.setAnimationsEnabled(false)
|
||||||
navigationStackCoordinator = NavigationStackCoordinator()
|
navigationStackCoordinator = NavigationStackCoordinator()
|
||||||
|
|
||||||
ServiceLocator.shared.register(userNotificationController: MockUserNotificationController())
|
ServiceLocator.shared.register(userNotificationController: MockUserNotificationController())
|
||||||
@@ -132,6 +133,40 @@ class MockScreen: Identifiable {
|
|||||||
roomAvatarUrl: "mock_url",
|
roomAvatarUrl: "mock_url",
|
||||||
emojiProvider: EmojiProvider())
|
emojiProvider: EmojiProvider())
|
||||||
return RoomScreenCoordinator(parameters: parameters)
|
return RoomScreenCoordinator(parameters: parameters)
|
||||||
|
case .roomSmallTimeline:
|
||||||
|
let timelineController = MockRoomTimelineController()
|
||||||
|
timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk
|
||||||
|
let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator,
|
||||||
|
timelineController: timelineController,
|
||||||
|
mediaProvider: MockMediaProvider(),
|
||||||
|
roomName: "New room",
|
||||||
|
roomAvatarUrl: "mock_url",
|
||||||
|
emojiProvider: EmojiProvider())
|
||||||
|
return RoomScreenCoordinator(parameters: parameters)
|
||||||
|
case .roomSmallTimelineIncomingAndSmallPagination:
|
||||||
|
let timelineController = MockRoomTimelineController()
|
||||||
|
timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk
|
||||||
|
timelineController.backPaginationResponses = [RoomTimelineItemFixtures.singleMessageChunk]
|
||||||
|
timelineController.incomingItems = [RoomTimelineItemFixtures.incomingMessage]
|
||||||
|
timelineController.simulateIncomingItems()
|
||||||
|
let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator,
|
||||||
|
timelineController: timelineController,
|
||||||
|
mediaProvider: MockMediaProvider(),
|
||||||
|
roomName: "Small timeline",
|
||||||
|
roomAvatarUrl: "mock_url",
|
||||||
|
emojiProvider: EmojiProvider())
|
||||||
|
return RoomScreenCoordinator(parameters: parameters)
|
||||||
|
case .roomSmallTimelineLargePagination:
|
||||||
|
let timelineController = MockRoomTimelineController()
|
||||||
|
timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk
|
||||||
|
timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk]
|
||||||
|
let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator,
|
||||||
|
timelineController: timelineController,
|
||||||
|
mediaProvider: MockMediaProvider(),
|
||||||
|
roomName: "Small timeline, paginating",
|
||||||
|
roomAvatarUrl: "mock_url",
|
||||||
|
emojiProvider: EmojiProvider())
|
||||||
|
return RoomScreenCoordinator(parameters: parameters)
|
||||||
case .sessionVerification:
|
case .sessionVerification:
|
||||||
let parameters = SessionVerificationCoordinatorParameters(sessionVerificationControllerProxy: MockSessionVerificationControllerProxy())
|
let parameters = SessionVerificationCoordinatorParameters(sessionVerificationControllerProxy: MockSessionVerificationControllerProxy())
|
||||||
return SessionVerificationCoordinator(parameters: parameters)
|
return SessionVerificationCoordinator(parameters: parameters)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ extension XCUIApplication {
|
|||||||
let lastLabel = staticTexts["lastItem"]
|
let lastLabel = staticTexts["lastItem"]
|
||||||
|
|
||||||
while !button.isHittable, !lastLabel.isHittable {
|
while !button.isHittable, !lastLabel.isHittable {
|
||||||
tables.firstMatch.swipeUp()
|
swipeUp()
|
||||||
}
|
}
|
||||||
|
|
||||||
button.tap()
|
button.tap()
|
||||||
|
|||||||
@@ -38,4 +38,28 @@ class RoomScreenUITests: XCTestCase {
|
|||||||
|
|
||||||
app.assertScreenshot(.roomEncryptedWithAvatar)
|
app.assertScreenshot(.roomEncryptedWithAvatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testSmallTimelineLayout() {
|
||||||
|
let app = Application.launch()
|
||||||
|
app.goToScreenWithIdentifier(.roomSmallTimeline)
|
||||||
|
|
||||||
|
// The messages should be bottom aligned.
|
||||||
|
app.assertScreenshot(.roomSmallTimeline)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSmallTimelineWithIncomingAndPagination() {
|
||||||
|
let app = Application.launch()
|
||||||
|
app.goToScreenWithIdentifier(.roomSmallTimelineIncomingAndSmallPagination)
|
||||||
|
|
||||||
|
// Wait for both the incoming message and the pagination chunk.
|
||||||
|
XCTAssert(app.staticTexts["Bob"].waitForExistence(timeout: 2))
|
||||||
|
XCTAssert(app.staticTexts["Helena"].waitForExistence(timeout: 2))
|
||||||
|
|
||||||
|
// The messages should still be bottom aligned after the new items are added.
|
||||||
|
app.assertScreenshot(.roomSmallTimelineIncomingAndSmallPagination)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSmallTimelineWithLargePagination() {
|
||||||
|
// To be implemented
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:96d580e92e1618c729240a00439801feccbfadf6bd7e00119a4df5b3724e1c82
|
||||||
|
size 92567
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:925c9edf55718ec2e1195fbe8a6e313f435eee075c703c74a487ca0425a60f2f
|
||||||
|
size 133380
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:3295b6e8348a37998c95f72285ae0bfc5651ec3166a376c327f482a0baa1e93d
|
||||||
|
size 114678
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:015eb7e93e193d635194bb6d0d67a3a8751180598fc63762ada0f94be11099e9
|
||||||
|
size 212903
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:12af6767660c17c4eaebdb951da4e61ac1cc365ba950e237fe8f08d4707f39a5
|
||||||
|
size 92342
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:087309a5c640fe574e3f80e9e8cbccef71bced0d49016a27c963d7bff07e24d1
|
||||||
|
size 133159
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:a365ef80c8bce284dfddd840433afe9fa6b3d7eee8521da98e065777a6819530
|
||||||
|
size 114689
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:31267576b8c4c8d038b3f5dde9e3f6c1f06c00b72cea3e5e9d02765e231fa682
|
||||||
|
size 212873
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:12af6767660c17c4eaebdb951da4e61ac1cc365ba950e237fe8f08d4707f39a5
|
||||||
|
size 92342
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:087309a5c640fe574e3f80e9e8cbccef71bced0d49016a27c963d7bff07e24d1
|
||||||
|
size 133159
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:180aae2e7f67beb59cfee31788efaf7f0a6b4fef910956ba1db1ed22edbfdc7f
|
||||||
|
size 114685
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:31267576b8c4c8d038b3f5dde9e3f6c1f06c00b72cea3e5e9d02765e231fa682
|
||||||
|
size 212873
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Timeline: Add a couple of basic tests to make sure the timeline is bottom aligned.
|
||||||
Reference in New Issue
Block a user