Skip to content

Commit 0134e5d

Browse files
[UI-1333] Splitting scene to separate channels and messages ones (#3)
[UI-1333] Created Patient Queue and Message List as separate screens
1 parent 26d91b0 commit 0134e5d

File tree

12 files changed

+357
-121
lines changed

12 files changed

+357
-121
lines changed

Examples.xcworkspace/contents.xcworkspacedata

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

telehealth-example/Telehealth/AppDelegate.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
5454
// shortly after application:didFinishLaunchingWithOptions.
5555
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
5656
}
57+
58+
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
59+
.portrait
60+
}
5761
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
//
2+
// ChatFlowCoordinator.swift
3+
//
4+
// PubNub Real-time Cloud-Hosted Push API and Push Notification Client Frameworks
5+
// Copyright © 2022 PubNub Inc.
6+
// https://www.pubnub.com/
7+
// https://www.pubnub.com/terms
8+
//
9+
// Permission is hereby granted, free of charge, to any person obtaining a copy
10+
// of this software and associated documentation files (the "Software"), to deal
11+
// in the Software without restriction, including without limitation the rights
12+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
// copies of the Software, and to permit persons to whom the Software is
14+
// furnished to do so, subject to the following conditions:
15+
//
16+
// The above copyright notice and this permission notice shall be included in
17+
// all copies or substantial portions of the Software.
18+
//
19+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
// THE SOFTWARE.
26+
//
27+
28+
import Foundation
29+
import UIKit
30+
import PubNub
31+
import PubNubChat
32+
import PubNubChatComponents
33+
34+
enum PatientError: Error {
35+
case membershipFetch(String)
36+
}
37+
38+
protocol ChatFlowCoordinator {
39+
func start() throws
40+
}
41+
42+
final class DefaultChatFlowCoordinator: ChatFlowCoordinator {
43+
private let navigationController: UINavigationController
44+
private let provider: TelehealthChatProvider
45+
46+
init(navigationController: UINavigationController, provider: TelehealthChatProvider) {
47+
self.navigationController = navigationController
48+
self.provider = provider
49+
}
50+
51+
func start() throws {
52+
navigationController.setNavigationBarHidden(false, animated: false)
53+
if provider.hasDoctorRole {
54+
try startWithDoctor()
55+
} else {
56+
try startWithPatient()
57+
}
58+
}
59+
}
60+
61+
//MARK: - Private
62+
private extension DefaultChatFlowCoordinator {
63+
private func startWithDoctor() throws {
64+
setUpChannelListViewController()
65+
}
66+
67+
private func startWithPatient() throws {
68+
let viewModel = try makeMessageViewModel()
69+
navigationController.pushViewController(
70+
viewModel.configuredComponentView(),
71+
animated: true
72+
)
73+
}
74+
75+
private func makeMessageViewModel() throws -> MessageListComponentViewModel<TelehealthCustomData, PubNubManagedChatEntities> {
76+
let currentUser = try provider.chatProvider.fetchCurrentUser()
77+
guard let membership = currentUser.memberships.first(where: { $0.managedUser.id == provider.uuid }) else {
78+
throw PatientError.membershipFetch("Cannot fetch membership for the current user")
79+
}
80+
81+
let messageListViewModel = try provider.chatProvider.messageListComponentViewModel(pubnubChannelId: membership.channelId)
82+
messageListViewModel.customNavigationTitleString = nil
83+
messageListViewModel.leftBarButtonNavigationItems = nil
84+
messageListViewModel.rightBarButtonNavigationItems = nil
85+
messageListViewModel.customNavigationTitleView = { viewModel in
86+
UIView.customUserView(
87+
with: membership.channel.name,
88+
secondaryLabelText: membership.channel.details,
89+
avatarURL: membership.channel.avatarURL,
90+
backgroundColor: .clear,
91+
primaryLabelTextColor: .white,
92+
secondaryLabelTextColor: .white
93+
)
94+
}
95+
96+
return messageListViewModel
97+
}
98+
99+
private func setUpChannelListViewController() {
100+
let viewModel = makeChannelViewModel()
101+
let channelListViewController = viewModel.configuredComponentView()
102+
channelListViewController.title = "Telehealth"
103+
navigationController.pushViewController(channelListViewController, animated: true)
104+
}
105+
106+
private func makeChannelViewModel() -> ChannelListComponentViewModel<TelehealthCustomData, PubNubManagedChatEntities> {
107+
let channelListViewModel = provider.chatProvider.senderMembershipsChanneListComponentViewModel()
108+
channelListViewModel.leftBarButtonNavigationItems = nil
109+
channelListViewModel.layoutShouldContainSupplimentaryViews = false
110+
channelListViewModel.didSelectChannel = { [weak self] viewController, viewModel, selectedChannel in
111+
self?.setupMessageListViewController(for: selectedChannel)
112+
}
113+
channelListViewModel.customNavigationTitleView = { viewModel in
114+
UIView.customChannelListNavigationItemTitleView()
115+
}
116+
return channelListViewModel
117+
}
118+
119+
private func setupMessageListViewController<Custom: ChannelCustomData>(for channel: ChatChannel<Custom>) {
120+
guard let messageListViewModel = try? provider.chatProvider.messageListComponentViewModel(pubnubChannelId: channel.id) else {
121+
preconditionFailure("Cannot create message list for the channel ID: \(channel.id)")
122+
}
123+
124+
messageListViewModel.customNavigationTitleString = nil
125+
messageListViewModel.rightBarButtonNavigationItems = nil
126+
messageListViewModel.customNavigationTitleView = { [weak self] viewModel in
127+
guard let name = channel.name, let self = self else { return UIView() }
128+
return self.customMessageListNavigationTitleView(for: name)
129+
}
130+
131+
let messageListViewController = messageListViewModel.configuredComponentView()
132+
navigationController.pushViewController(messageListViewController, animated: true)
133+
}
134+
135+
private func customMessageListNavigationTitleView(for name: String) -> UIView {
136+
let label = UILabel()
137+
label.text = name
138+
label.font = UIFont(name: "Poppins-Bold", size: 16)
139+
return label
140+
}
141+
}

telehealth-example/Telehealth/Login/LoginViewController.swift

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@
2828
import UIKit
2929
import PubNubChat
3030

31-
class LoginViewController: UIViewController {
31+
final class LoginViewController: UIViewController {
3232

3333
@IBOutlet private var infoLabel: UILabel!
3434
@IBOutlet private var loginTextField: UITextField!
3535
@IBOutlet private var passwordTextField: UITextField!
3636
@IBOutlet private var errorView: UIView!
3737

3838
private var provider: TelehealthChatProvider?
39+
private var coordinator: ChatFlowCoordinator?
3940

4041
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
4142
view.endEditing(true)
@@ -63,7 +64,6 @@ class LoginViewController: UIViewController {
6364
}
6465

6566
@IBAction func onLoginButtonTapped(_ sender: UIButton) {
66-
6767
provider = TelehealthChatProvider(with: loginTextField.text ?? String(), completion: { [weak self] in
6868
self?.configureFinalViewController()
6969
})
@@ -72,58 +72,22 @@ class LoginViewController: UIViewController {
7272
}
7373

7474
private func configureFinalViewController() {
75-
76-
guard let provider = provider else {
75+
guard let provider = provider, let navigationController = navigationController else {
76+
print("encountered nil during configuration")
7777
return
7878
}
79-
80-
if provider.hasDoctorRole {
81-
navigationController?.pushViewController(
82-
CustomSplitViewController(provider: provider),
83-
animated: true
84-
)
85-
} else {
86-
navigationController?.setNavigationBarHidden(false, animated: false)
87-
setUpMessageListForPatient(using: provider)
88-
}
89-
}
90-
91-
private func setUpMessageListForPatient(using provider: TelehealthChatProvider) {
92-
93-
guard let currentUser = try? provider.chatProvider.fetchCurrentUser() else {
94-
preconditionFailure("Cannot fetch current user")
95-
}
96-
guard let membership = currentUser.memberships.first(where: { $0.managedUser.id == provider.uuid }) else {
97-
preconditionFailure("Cannot fetch membership for the current user")
98-
}
99-
guard let messageListViewModel = try? provider.chatProvider.messageListComponentViewModel(pubnubChannelId: membership.channelId) else {
100-
preconditionFailure("Cannot create message list for the channel ID: \(membership.channelId)")
101-
}
102-
103-
messageListViewModel.customNavigationTitleString = nil
104-
messageListViewModel.leftBarButtonNavigationItems = nil
105-
messageListViewModel.rightBarButtonNavigationItems = nil
106-
messageListViewModel.customNavigationTitleView = { viewModel in
107-
UIView.customUserView(
108-
with: membership.channel.name,
109-
secondaryLabelText: membership.channel.details,
110-
avatarURL: membership.channel.avatarURL,
111-
backgroundColor: .clear,
112-
primaryLabelTextColor: .white,
113-
secondaryLabelTextColor: .white
114-
)
79+
80+
do {
81+
coordinator = DefaultChatFlowCoordinator(navigationController: navigationController, provider: provider)
82+
try coordinator?.start()
83+
} catch {
84+
print(error)
11585
}
116-
117-
self.navigationController?.pushViewController(
118-
messageListViewModel.configuredComponentView(),
119-
animated: true
120-
)
12186
}
12287

12388
@IBAction func onInfoLabelTapped(_ sender: UIGestureRecognizer) {
124-
let url = URL(string: "https://www.google.pl")!
125-
126-
if UIApplication.shared.canOpenURL(url) {
89+
let link = "https://github.com/pubnub/chat-components-ios-examples/tree/master/telehealth-example#usernames"
90+
if let url = URL(string: link), UIApplication.shared.canOpenURL(url) {
12791
UIApplication.shared.open(url)
12892
}
12993
}

telehealth-example/Telehealth/PubNub/TelehealthChatProvider.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ import PubNub
3030
import PubNubChat
3131
import PubNubChatComponents
3232

33-
class TelehealthChatProvider {
34-
35-
let PUBNUB_PUB_KEY = "pub-c-8aa2a3e0-4047-4e8c-b966-a8f9d27e3269"
36-
let PUBNUB_SUB_KEY = "sub-c-5dfc52c0-b3e1-11ec-9e6b-d29fac035801"
33+
final class TelehealthChatProvider {
34+
35+
// Please enter the subkey that you acquire from Admin Portal or from the tutorial here,
36+
// and repeat this step for all your other devices used for this demo
37+
let PUBNUB_PUB_KEY = "myPublishKey"
38+
let PUBNUB_SUB_KEY = "myPublishKey"
3739

3840
private(set) var uuid: String = String()
3941
private(set) var hasDoctorRole: Bool = false
@@ -120,7 +122,6 @@ class TelehealthChatProvider {
120122
provider.themeProvider.template.messageInputComponent = messageInputComponentTheme
121123

122124
return provider
123-
124125
}()
125126

126127
private func insertObjects(
@@ -129,7 +130,6 @@ class TelehealthChatProvider {
129130
memberships: [ChatMember<TelehealthCustomData>],
130131
completion: (() -> Void )? = nil
131132
) {
132-
133133
chatProvider.pubnubProvider.subscribe(
134134
SubscribeRequest(
135135
channels: (channels.filter() { $0.id.contains(uuid) }).map() { $0.id },

telehealth-example/Telehealth/PubNub/Theming/ChannelList/ChannelListCollectionViewLayout.swift

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,34 @@
11
//
2-
// CustomChannelListCollectionViewLayout.swift
3-
// Telehealth
2+
// ChannelListCollectionViewLayout.swift
43
//
5-
// Created by Jakub Guz on 8/8/22.
4+
// PubNub Real-time Cloud-Hosted Push API and Push Notification Client Frameworks
5+
// Copyright © 2022 PubNub Inc.
6+
// https://www.pubnub.com/
7+
// https://www.pubnub.com/terms
8+
//
9+
// Permission is hereby granted, free of charge, to any person obtaining a copy
10+
// of this software and associated documentation files (the "Software"), to deal
11+
// in the Software without restriction, including without limitation the rights
12+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
// copies of the Software, and to permit persons to whom the Software is
14+
// furnished to do so, subject to the following conditions:
15+
//
16+
// The above copyright notice and this permission notice shall be included in
17+
// all copies or substantial portions of the Software.
18+
//
19+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
// THE SOFTWARE.
626
//
727

828
import UIKit
929
import PubNubChatComponents
1030

11-
class ChannelListCollectionViewLayout: UICollectionViewLayout, CollectionViewLayoutComponent {
31+
final class ChannelListCollectionViewLayout: UICollectionViewLayout, CollectionViewLayoutComponent {
1232
static func create(usingSupplimentaryItems: Bool) -> UICollectionViewLayout {
1333

1434
let itemSize = NSCollectionLayoutSize(

telehealth-example/Telehealth/PubNub/Theming/ChannelList/ChannelListItemCell.swift

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,35 @@
11
//
22
// ChannelListItemCell.swift
3-
// Telehealth
43
//
5-
// Created by Jakub Guz on 8/8/22.
4+
// PubNub Real-time Cloud-Hosted Push API and Push Notification Client Frameworks
5+
// Copyright © 2022 PubNub Inc.
6+
// https://www.pubnub.com/
7+
// https://www.pubnub.com/terms
8+
//
9+
// Permission is hereby granted, free of charge, to any person obtaining a copy
10+
// of this software and associated documentation files (the "Software"), to deal
11+
// in the Software without restriction, including without limitation the rights
12+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
// copies of the Software, and to permit persons to whom the Software is
14+
// furnished to do so, subject to the following conditions:
15+
//
16+
// The above copyright notice and this permission notice shall be included in
17+
// all copies or substantial portions of the Software.
18+
//
19+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
// THE SOFTWARE.
626
//
727

828
import UIKit
929
import PubNubChatComponents
1030

11-
class ChannelListItemCell: ChannelMemberComponentCell {
12-
31+
final class ChannelListItemCell: ChannelMemberComponentCell {
1332
override func setupSubviews() {
14-
1533
super.setupSubviews()
1634
cellContainer.spacing = 11
1735

0 commit comments

Comments
 (0)