Skip to content

Commit b5d163f

Browse files
committed
Merge branch 'master' into development
# Conflicts: # Example/ChatExample.xcodeproj/project.pbxproj # Example/Sources/View Controllers/LaunchViewController.swift # README.md
2 parents cbc908b + 39e4ad5 commit b5d163f

File tree

7 files changed

+214
-22
lines changed

7 files changed

+214
-22
lines changed

Example/ChatExample.xcodeproj/project.pbxproj

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10-
1F16CA6DDBA8B2AED7933182 /* Pods_ChatExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5667D3D8E25D4659A3133C2 /* Pods_ChatExample.framework */; };
10+
1C5433DD24C389C300A5383B /* MessagesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5433DC24C389C300A5383B /* MessagesView.swift */; };
11+
1C5433DF24C38DBF00A5383B /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C5433DE24C38DBF00A5383B /* SwiftUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
12+
1C5433E224C3A33600A5383B /* SwiftUIExampleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5433E124C3A33600A5383B /* SwiftUIExampleView.swift */; };
1113
383B9EB32172A1C4008AB91A /* MockUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 383B9EB22172A1C4008AB91A /* MockUser.swift */; };
1214
385C2922211FF32E0010B4BA /* CustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 385C2920211FF32E0010B4BA /* CustomCell.swift */; };
1315
385C2923211FF32E0010B4BA /* TableViewCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 385C2921211FF32E0010B4BA /* TableViewCells.swift */; };
@@ -72,10 +74,11 @@
7274
/* End PBXCopyFilesBuildPhase section */
7375

7476
/* Begin PBXFileReference section */
75-
10FACBA391F222F83B0D0F14 /* Pods_ChatExampleUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ChatExampleUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
76-
14FD0CD310DC61B22EE2F774 /* Pods-ChatExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatExampleTests.debug.xcconfig"; path = "Target Support Files/Pods-ChatExampleTests/Pods-ChatExampleTests.debug.xcconfig"; sourceTree = "<group>"; };
77-
15E7C4C168DF654D009EE593 /* Pods-ChatExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatExample.release.xcconfig"; path = "Target Support Files/Pods-ChatExample/Pods-ChatExample.release.xcconfig"; sourceTree = "<group>"; };
78-
19FCAA41E5FB273F95706474 /* Pods-ChatExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatExample.debug.xcconfig"; path = "Target Support Files/Pods-ChatExample/Pods-ChatExample.debug.xcconfig"; sourceTree = "<group>"; };
77+
0364943D08CDBE656E6F6DF8 /* Pods-ChatExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatExampleTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ChatExampleTests/Pods-ChatExampleTests.debug.xcconfig"; sourceTree = "<group>"; };
78+
1C5433DC24C389C300A5383B /* MessagesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagesView.swift; sourceTree = "<group>"; };
79+
1C5433DE24C38DBF00A5383B /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
80+
1C5433E124C3A33600A5383B /* SwiftUIExampleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIExampleView.swift; sourceTree = "<group>"; };
81+
2AC6E3F5C11E39F57598DBE6 /* Pods_ChatExampleUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ChatExampleUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7982
383B9EB22172A1C4008AB91A /* MockUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockUser.swift; sourceTree = "<group>"; };
8083
385C2920211FF32E0010B4BA /* CustomCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomCell.swift; sourceTree = "<group>"; };
8184
385C2921211FF32E0010B4BA /* TableViewCells.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCells.swift; sourceTree = "<group>"; };
@@ -123,7 +126,8 @@
123126
isa = PBXFrameworksBuildPhase;
124127
buildActionMask = 2147483647;
125128
files = (
126-
1F16CA6DDBA8B2AED7933182 /* Pods_ChatExample.framework in Frameworks */,
129+
1C5433DF24C38DBF00A5383B /* SwiftUI.framework in Frameworks */,
130+
C7CA53A1B85256A5097E7DC7 /* Pods_ChatExample.framework in Frameworks */,
127131
);
128132
runOnlyForDeploymentPostprocessing = 0;
129133
};
@@ -146,19 +150,19 @@
146150
/* End PBXFrameworksBuildPhase section */
147151

148152
/* Begin PBXGroup section */
149-
13FCBEED2424D36900CB489F /* Resources */ = {
153+
1C5433E024C3A32400A5383B /* SwiftUI */ = {
150154
isa = PBXGroup;
151155
children = (
152-
882B5E7F1CF7D53600B6E160 /* Info.plist */,
153-
882B5E791CF7D53600B6E160 /* Assets.xcassets */,
154-
882B5E7A1CF7D53600B6E160 /* LaunchScreen.storyboard */,
156+
1C5433DC24C389C300A5383B /* MessagesView.swift */,
157+
1C5433E124C3A33600A5383B /* SwiftUIExampleView.swift */,
155158
);
156-
path = Resources;
159+
path = SwiftUI;
157160
sourceTree = "<group>";
158161
};
159162
385C2924211FF3310010B4BA /* Views */ = {
160163
isa = PBXGroup;
161164
children = (
165+
1C5433E024C3A32400A5383B /* SwiftUI */,
162166
385C2920211FF32E0010B4BA /* CustomCell.swift */,
163167
385C2921211FF32E0010B4BA /* TableViewCells.swift */,
164168
);
@@ -309,9 +313,10 @@
309313
955AE3B8EFF8FDB8F572D3F7 /* Frameworks */ = {
310314
isa = PBXGroup;
311315
children = (
312-
C5667D3D8E25D4659A3133C2 /* Pods_ChatExample.framework */,
313-
4E9F9C2F0EDEAB72320FDD25 /* Pods_ChatExampleTests.framework */,
314-
10FACBA391F222F83B0D0F14 /* Pods_ChatExampleUITests.framework */,
316+
1C5433DE24C38DBF00A5383B /* SwiftUI.framework */,
317+
3B316705C4717C3B4C916D62 /* Pods_ChatExample.framework */,
318+
56F0AC85B38034EC92CCBC7D /* Pods_ChatExampleTests.framework */,
319+
2AC6E3F5C11E39F57598DBE6 /* Pods_ChatExampleUITests.framework */,
315320
);
316321
name = Frameworks;
317322
sourceTree = "<group>";
@@ -566,6 +571,7 @@
566571
files = (
567572
385C2922211FF32E0010B4BA /* CustomCell.swift in Sources */,
568573
385C2946211FF38F0010B4BA /* LaunchViewController.swift in Sources */,
574+
1C5433E224C3A33600A5383B /* SwiftUIExampleView.swift in Sources */,
569575
385C2939211FF37B0010B4BA /* Lorem.swift in Sources */,
570576
385C2928211FF33B0010B4BA /* MockMessage.swift in Sources */,
571577
63ECDABE24182A470016C349 /* MessageSubviewViewController.swift in Sources */,
@@ -583,6 +589,7 @@
583589
385C2943211FF38F0010B4BA /* SettingsViewController.swift in Sources */,
584590
385C2927211FF33B0010B4BA /* MockSocket.swift in Sources */,
585591
385C2947211FF38F0010B4BA /* BasicExampleViewController.swift in Sources */,
592+
1C5433DD24C389C300A5383B /* MessagesView.swift in Sources */,
586593
882B5E811CF7D53600B6E160 /* AppDelegate.swift in Sources */,
587594
385C292D211FF3520010B4BA /* CustomMessageFlowLayout.swift in Sources */,
588595
38CCCC592258419300DD5482 /* AutocompleteExampleViewController.swift in Sources */,

Example/Sources/Data Generation/SampleData.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,21 @@ final internal class SampleData {
223223
completion(messages)
224224
}
225225

226+
func getMessages(count: Int) -> [MockMessage] {
227+
var messages: [MockMessage] = []
228+
// Disable Custom Messages
229+
UserDefaults.standard.set(false, forKey: "Custom Messages")
230+
for _ in 0..<count {
231+
let uniqueID = UUID().uuidString
232+
let user = senders.random()!
233+
let date = dateAddingRandomTime()
234+
let randomSentence = Lorem.sentence()
235+
let message = MockMessage(text: randomSentence, user: user, messageId: uniqueID, date: date)
236+
messages.append(message)
237+
}
238+
return messages
239+
}
240+
226241
func getAdvancedMessages(count: Int, completion: ([MockMessage]) -> Void) {
227242
var messages: [MockMessage] = []
228243
// Enable Custom Messages

Example/Sources/View Controllers/LaunchViewController.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,15 @@
2525
import UIKit
2626
import MessageKit
2727
import SafariServices
28+
import SwiftUI
2829

2930
final internal class LaunchViewController: UITableViewController {
3031

3132
override var preferredStatusBarStyle: UIStatusBarStyle {
3233
return .lightContent
3334
}
3435

35-
let cells = ["Basic Example", "Advanced Example", "Autocomplete Example", "Embedded Example", "Subview Example", "Settings", "Source Code", "Contributors"]
36+
let cells = ["Basic Example", "Advanced Example", "Autocomplete Example", "Embedded Example", "Subview Example", "SwiftUI Example", "Settings", "Source Code", "Contributors"]
3637

3738
// MARK: - View Life Cycle
3839

@@ -86,9 +87,11 @@ final internal class LaunchViewController: UITableViewController {
8687
let detailViewController = NavigationController(rootViewController: viewController)
8788
splitViewController?.showDetailViewController(detailViewController, sender: self)
8889
case "Embedded Example":
89-
let viewController = MessageContainerController()
90-
let detailViewController = NavigationController(rootViewController: viewController)
91-
splitViewController?.showDetailViewController(detailViewController, sender: self)
90+
navigationController?.pushViewController(MessageContainerController(), animated: true)
91+
case "SwiftUI Example":
92+
if #available(iOS 13, *) {
93+
navigationController?.pushViewController(UIHostingController(rootView: SwiftUIExampleView()), animated: true)
94+
}
9295
case "Settings":
9396
let viewController = SettingsViewController()
9497
let detailViewController = NavigationController(rootViewController: viewController)
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
//
2+
// MessagesView.swift
3+
// ChatExample
4+
//
5+
// Created by Kino Roy on 2020-07-18.
6+
// Copyright © 2020 MessageKit. All rights reserved.
7+
//
8+
9+
import SwiftUI
10+
import MessageKit
11+
import InputBarAccessoryView
12+
13+
final class MessageSwiftUIVC: MessagesViewController {
14+
override func viewDidAppear(_ animated: Bool) {
15+
super.viewDidAppear(animated)
16+
// Because SwiftUI wont automatically make our controller the first responder, we need to do it on viewDidAppear
17+
becomeFirstResponder()
18+
messagesCollectionView.scrollToBottom(animated: true)
19+
}
20+
}
21+
22+
@available(iOS 13.0, *)
23+
struct MessagesView: UIViewControllerRepresentable {
24+
25+
@State var initialized = false
26+
@Binding var messages: [MessageType]
27+
28+
func makeUIViewController(context: Context) -> MessagesViewController {
29+
let messagesVC = MessageSwiftUIVC()
30+
31+
messagesVC.messagesCollectionView.messagesDisplayDelegate = context.coordinator
32+
messagesVC.messagesCollectionView.messagesLayoutDelegate = context.coordinator
33+
messagesVC.messagesCollectionView.messagesDataSource = context.coordinator
34+
messagesVC.messageInputBar.delegate = context.coordinator
35+
messagesVC.scrollsToBottomOnKeyboardBeginsEditing = true // default false
36+
messagesVC.maintainPositionOnKeyboardFrameChanged = true // default false
37+
38+
return messagesVC
39+
}
40+
41+
func updateUIViewController(_ uiViewController: MessagesViewController, context: Context) {
42+
uiViewController.messagesCollectionView.reloadData()
43+
scrollToBottom(uiViewController)
44+
}
45+
46+
private func scrollToBottom(_ uiViewController: MessagesViewController) {
47+
DispatchQueue.main.async {
48+
// The initialized state variable allows us to start at the bottom with the initial messages without seeing the inital scroll flash by
49+
uiViewController.messagesCollectionView.scrollToBottom(animated: self.initialized)
50+
self.initialized = true
51+
}
52+
}
53+
54+
func makeCoordinator() -> Coordinator {
55+
return Coordinator(messages: $messages)
56+
}
57+
58+
final class Coordinator {
59+
60+
let formatter: DateFormatter = {
61+
let formatter = DateFormatter()
62+
formatter.dateStyle = .medium
63+
return formatter
64+
}()
65+
66+
var messages: Binding<[MessageType]>
67+
init(messages: Binding<[MessageType]>) {
68+
self.messages = messages
69+
}
70+
71+
}
72+
73+
}
74+
75+
@available(iOS 13.0, *)
76+
extension MessagesView.Coordinator: MessagesDataSource {
77+
func currentSender() -> SenderType {
78+
return SampleData.shared.currentSender
79+
}
80+
81+
func messageForItem(at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> MessageType {
82+
return messages.wrappedValue[indexPath.section]
83+
}
84+
85+
func numberOfSections(in messagesCollectionView: MessagesCollectionView) -> Int {
86+
return messages.wrappedValue.count
87+
}
88+
89+
func messageTopLabelAttributedText(for message: MessageType, at indexPath: IndexPath) -> NSAttributedString? {
90+
let name = message.sender.displayName
91+
return NSAttributedString(string: name, attributes: [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .caption1)])
92+
}
93+
94+
func messageBottomLabelAttributedText(for message: MessageType, at indexPath: IndexPath) -> NSAttributedString? {
95+
let dateString = formatter.string(from: message.sentDate)
96+
return NSAttributedString(string: dateString, attributes: [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .caption2)])
97+
}
98+
}
99+
100+
@available(iOS 13.0, *)
101+
extension MessagesView.Coordinator: InputBarAccessoryViewDelegate {
102+
func inputBar(_ inputBar: InputBarAccessoryView, didPressSendButtonWith text: String) {
103+
let message = MockMessage(text: text, user: SampleData.shared.currentSender, messageId: UUID().uuidString, date: Date())
104+
messages.wrappedValue.append(message)
105+
inputBar.inputTextView.text = ""
106+
}
107+
}
108+
109+
@available(iOS 13.0, *)
110+
extension MessagesView.Coordinator: MessagesLayoutDelegate, MessagesDisplayDelegate {
111+
func configureAvatarView(_ avatarView: AvatarView, for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) {
112+
let avatar = SampleData.shared.getAvatarFor(sender: message.sender)
113+
avatarView.set(avatar: avatar)
114+
}
115+
func messageTopLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
116+
return 20
117+
}
118+
119+
func messageBottomLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
120+
return 16
121+
}
122+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// ChatView.swift
3+
// ChatExample
4+
//
5+
// Created by Kino Roy on 2020-07-18.
6+
// Copyright © 2020 MessageKit. All rights reserved.
7+
//
8+
9+
import SwiftUI
10+
import MessageKit
11+
12+
@available(iOS 13.0, *)
13+
struct SwiftUIExampleView: View {
14+
15+
@State var messages: [MessageType] = SampleData.shared.getMessages(count: 20)
16+
17+
var body: some View {
18+
MessagesView(messages: $messages).onAppear {
19+
self.connectToMessageSocket()
20+
}.onDisappear {
21+
self.cleanupSocket()
22+
}
23+
.navigationBarTitle("SwiftUI Example", displayMode: .inline)
24+
}
25+
26+
private func connectToMessageSocket() {
27+
MockSocket.shared.connect(with: [SampleData.shared.nathan, SampleData.shared.wu]).onNewMessage { message in
28+
self.messages.append(message)
29+
}
30+
}
31+
32+
private func cleanupSocket() {
33+
MockSocket.shared.disconnect()
34+
}
35+
36+
}
37+
38+
@available(iOS 13.0, *)
39+
struct SwiftUIExampleView_Previews: PreviewProvider {
40+
static var previews: some View {
41+
SwiftUIExampleView()
42+
}
43+
}

GitHubActions/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ if [ "$MODE" = "example" -o "$MODE" = "all" ]; then
5353
gem install bundler
5454
bundle check || bundle install
5555
bundle exec pod install
56-
set -o pipefail && xcodebuild build analyze -workspace ChatExample.xcworkspace -scheme ChatExample -destination "platform=iOS Simulator,name=iPhone 11 Pro" ONLY_ACTIVE_ARCH=NO CODE_SIGNING_REQUIRED=NO | xcpretty -c
56+
set -o pipefail && xcodebuild build analyze -workspace ChatExample.xcworkspace -scheme ChatExample -destination "platform=iOS Simulator,name=iPhone 11 Pro" CODE_SIGNING_REQUIRED=NO | xcpretty -c
5757
success="1"
5858
fi
5959

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ The `MessageInputBar`, derrived from [InputBarAccessoryView](https://github.com/
114114

115115
Please have a look at the [Quick Start guide](https://github.com/MessageKit/MessageKit/blob/master/Documentation/QuickStart.md) and the [FAQs](https://github.com/MessageKit/MessageKit/blob/master/Documentation/FAQs.md).
116116

117-
We recommend you start by looking at the [Example](https://github.com/MessageKit/MessageKit/tree/master/Example) project or write a question with the "messagekit" tag on [Stack Overflow](https://stackoverflow.com/questions/tagged/messagekit). You can also look at previous issues here on GitHib with the **"Question"** tag.
117+
We recommend you start by looking at the [Example](https://github.com/MessageKit/MessageKit/tree/master/Example) project or write a question with the "messagekit" tag on [Stack Overflow](https://stackoverflow.com/questions/tagged/messagekit). You can also look at previous issues here on GitHub with the **"Question"** tag.
118118

119119
For more on how to use the MessageInputBar, see the dependency it is based on [InputBarAccessoryView](https://github.com/nathantannar4/InputBarAccessoryView). You can also see this [short guide]([https://github.com/MessageKit/MessageKit/blob/master/Documentation/MessageInputBar.md)
120120

@@ -163,8 +163,9 @@ Great! Look over these things first.
163163
- Download the project and check out the current code base. Suggest any improvements by opening a new issue.
164164
- Check out the [What's Next](#whats-next) section :point_down: to see where we are headed.
165165
- Check [StackOverflow](https://stackoverflow.com/questions/tagged/messagekit)
166-
- Install [SwiftLint](https://github.com/realm/SwiftLint) too keep yourself in :neckbeard: style.
167-
- Be kind and helpful.
166+
- Install [SwiftLint](https://github.com/realm/SwiftLint) to keep yourself in :neckbeard: style.
167+
- Be kind and helpful.
168+
168169

169170
## What's Next?
170171

@@ -190,6 +191,7 @@ Add your app to the list of apps using this library and make a pull request.
190191
- [Studievenn](https://studievenn.no)
191192
- [SmooveText](https://apps.apple.com/np/app/smoove-text/id1362792811)
192193
- [COYO Engage](https://apps.apple.com/app/coyo-engage/id1341588804)
194+
- [HitchPin](https://www.hitchpin.com)
193195

194196
_Please provide attribution, it is greatly appreciated._
195197

0 commit comments

Comments
 (0)