Skip to content

Commit

Permalink
0.0.10 Release
Browse files Browse the repository at this point in the history
  • Loading branch information
gzerad committed Aug 17, 2021
1 parent 7a29e10 commit 8eeb65c
Show file tree
Hide file tree
Showing 49 changed files with 1,555 additions and 396 deletions.
35 changes: 33 additions & 2 deletions Example/HMSSDKExample/Meeting/Chat/Base.lproj/Chat.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="Image references" minToolsVersion="12.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="Stack View standard spacing" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
Expand All @@ -18,8 +19,31 @@
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Send Message to" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HqQ-oH-c6B">
<rect key="frame" x="15" y="88" width="146.5" height="48"/>
<constraints>
<constraint firstAttribute="height" constant="48" id="v3A-QY-uD6"/>
</constraints>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle2"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="USP-0B-WSu">
<rect key="frame" x="169.5" y="100.5" width="224.5" height="23"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="148" id="a38-xX-z7J"/>
</constraints>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle2"/>
<state key="normal" title="Everyone">
<color key="titleColor" systemColor="linkColor"/>
<imageReference key="image" image="chevron.down.circle" catalog="system" symbolScale="medium"/>
<preferredSymbolConfiguration key="preferredSymbolConfiguration" configurationType="font" scale="large" weight="regular">
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle1"/>
</preferredSymbolConfiguration>
</state>
</button>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" keyboardDismissMode="interactive" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" translatesAutoresizingMaskIntoConstraints="NO" id="9fl-FC-tEx">
<rect key="frame" x="0.0" y="96" width="414" height="766"/>
<rect key="frame" x="0.0" y="144" width="414" height="718"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<stackView key="tableFooterView" opaque="NO" contentMode="scaleToFill" spacingType="standard" id="lf7-Ev-kp2">
<rect key="frame" x="0.0" y="112.5" width="414" height="44"/>
Expand Down Expand Up @@ -124,19 +148,25 @@
<viewLayoutGuide key="safeArea" id="0sl-s8-x4X"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="HqQ-oH-c6B" firstAttribute="top" secondItem="Vtf-9d-egJ" secondAttribute="bottom" id="2yh-pW-gjx"/>
<constraint firstItem="Vtf-9d-egJ" firstAttribute="top" secondItem="cjX-ww-GBI" secondAttribute="top" id="5dZ-bq-1ls"/>
<constraint firstItem="Vtf-9d-egJ" firstAttribute="centerX" secondItem="aED-Ka-zya" secondAttribute="centerX" id="6wj-j5-30S"/>
<constraint firstItem="9fl-FC-tEx" firstAttribute="top" secondItem="HqQ-oH-c6B" secondAttribute="bottom" constant="8" symbolic="YES" id="AVS-Bs-FtG"/>
<constraint firstItem="USP-0B-WSu" firstAttribute="trailing" secondItem="cjX-ww-GBI" secondAttribute="trailing" id="AeN-Ph-6u3"/>
<constraint firstItem="cjX-ww-GBI" firstAttribute="leading" secondItem="Vtf-9d-egJ" secondAttribute="trailing" constant="8" symbolic="YES" id="HHg-Gq-4hh"/>
<constraint firstItem="9fl-FC-tEx" firstAttribute="leading" secondItem="0sl-s8-x4X" secondAttribute="leading" id="Hva-jO-VPI"/>
<constraint firstItem="USP-0B-WSu" firstAttribute="leading" secondItem="HqQ-oH-c6B" secondAttribute="trailing" constant="8" symbolic="YES" id="Kr4-Kb-9Bf"/>
<constraint firstItem="0sl-s8-x4X" firstAttribute="trailing" secondItem="cjX-ww-GBI" secondAttribute="trailing" constant="20" id="MfM-8h-mz3"/>
<constraint firstItem="9fl-FC-tEx" firstAttribute="top" secondItem="Vtf-9d-egJ" secondAttribute="bottom" constant="8" symbolic="YES" id="RsJ-kR-iTu"/>
<constraint firstItem="0sl-s8-x4X" firstAttribute="bottom" secondItem="9fl-FC-tEx" secondAttribute="bottom" id="b8Q-Pv-bdq"/>
<constraint firstItem="USP-0B-WSu" firstAttribute="centerY" secondItem="HqQ-oH-c6B" secondAttribute="centerY" id="cG0-dL-sWv"/>
<constraint firstItem="Vtf-9d-egJ" firstAttribute="bottom" secondItem="cjX-ww-GBI" secondAttribute="bottom" id="cdR-uE-mjp"/>
<constraint firstItem="HqQ-oH-c6B" firstAttribute="leading" secondItem="0sl-s8-x4X" secondAttribute="leading" constant="15" id="d0K-JC-6zW"/>
<constraint firstItem="0sl-s8-x4X" firstAttribute="trailing" secondItem="9fl-FC-tEx" secondAttribute="trailing" id="gCU-RM-Yl9"/>
<constraint firstItem="cjX-ww-GBI" firstAttribute="top" secondItem="0sl-s8-x4X" secondAttribute="top" id="jOs-4n-yLo"/>
</constraints>
</view>
<connections>
<outlet property="receiverButton" destination="USP-0B-WSu" id="LMy-Ul-2cj"/>
<outlet property="sendButton" destination="oGr-jo-9WQ" id="ptG-2T-KIy"/>
<outlet property="stackView" destination="lf7-Ev-kp2" id="KH3-Va-F4K"/>
<outlet property="table" destination="9fl-FC-tEx" id="ZP0-IB-Wzb"/>
Expand All @@ -150,6 +180,7 @@
</scenes>
<resources>
<image name="arrow.up.circle.fill" catalog="system" width="128" height="121"/>
<image name="chevron.down.circle" catalog="system" width="128" height="121"/>
<image name="message" catalog="system" width="128" height="113"/>
<systemColor name="labelColor">
<color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
Expand Down
144 changes: 124 additions & 20 deletions Example/HMSSDKExample/Meeting/Chat/ChatViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,61 @@ final class ChatViewController: UIViewController {
@IBOutlet private weak var stackView: UIStackView!
@IBOutlet private weak var textField: UITextField!
@IBOutlet private weak var sendButton: UIButton!

@IBOutlet weak var receiverButton: UIButton! {
didSet {
if #available(iOS 14.0, *) {
receiverButton.menu = menu
receiverButton.showsMenuAsPrimaryAction = true
} else {
// Fallback on earlier versions
}
}
}

typealias DataSource = UITableViewDiffableDataSource<ChatSection, HMSMessage>
typealias Snapshot = NSDiffableDataSourceSnapshot<ChatSection, HMSMessage>

private lazy var dataSource = makeDataSource()

var menu: UIMenu {
UIMenu(title: "Send Message to", image: nil, identifier: nil, options: [], children: menuItems)
}

var menuItems: [UIAction] {

var result = [
UIAction(title: "Everyone",
image: UIImage(systemName: "speaker.wave.3")?.withTintColor(.link)) { [weak self] _ in
self?.selectedRecipient = nil // implies send message to all
self?.receiverButton.setTitle("Everyone", for: .normal)
}
]

if let roles = interactor?.hmsSDK?.roles {
roles.forEach { role in
result.append(UIAction(title: role.name, image: nil) { [weak self] _ in
self?.selectedRecipient = role
self?.receiverButton.setTitle(role.name, for: .normal)
})
}
}

if let peers = interactor?.hmsSDK?.remotePeers {
let sortedPeers = peers.sorted { $0.name < $1.name }

sortedPeers.forEach { peer in
result.append(UIAction(title: peer.name, image: nil) { [weak self] _ in
self?.selectedRecipient = peer
self?.receiverButton.setTitle(peer.name, for: .normal)
})
}
}

return result
}

var selectedRecipient: AnyObject?


// MARK: - View Lifecycle

Expand All @@ -35,14 +85,18 @@ final class ChatViewController: UIViewController {

observeBroadcast()
handleKeyboard()
applySnapshot()
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
textField.becomeFirstResponder()
}


override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
applySnapshot()
}

deinit {
NotificationCenter.default.removeObserver(self)
}
Expand Down Expand Up @@ -91,32 +145,54 @@ final class ChatViewController: UIViewController {
}

@IBAction private func sendTapped(_ sender: UIButton) {

guard let message = textField.text,
!message.isEmpty,
let interactor = interactor,
let peerID = interactor.hmsSDK?.localPeer?.peerID else { return }
let interactor = interactor
else { return }

sender.isEnabled = false

let messageHandler: ((HMSMessage?, HMSError?) -> Void) = { [weak self, weak sender] message, error in
sender?.isEnabled = true

if let message = message {
self?.append(message)
} else if let error = error {
self?.showMessageSendError(error)
}
}

let broadcast = HMSMessage(sender: peerID,
receiver: "",
time: "\(Date())",
type: "chat",
message: message)
switch selectedRecipient {
case is HMSRole:
interactor.hmsSDK?.sendGroupMessage(message: message, roles: [selectedRecipient as! HMSRole], completion: messageHandler)
case is HMSPeer:
interactor.hmsSDK?.sendDirectMessage(message: message, peer: (selectedRecipient as! HMSPeer), completion: messageHandler)
default:
interactor.hmsSDK?.sendBroadcastMessage(message: message, completion: messageHandler)
}
}

private func showMessageSendError(_ error: HMSError) {
let title = "Could Not Send a Message"

interactor.hmsSDK?.send(message: broadcast)
let alertController = UIAlertController(title: title,
message: error.message,
preferredStyle: .alert)


interactor.messages.append(broadcast)
alertController.addAction(UIAlertAction(title: "Ok", style: .cancel))

present(alertController, animated: true)
}

private func append(_ message: HMSMessage) {
interactor?.messages.append(message)
applySnapshot()

if let index = dataSource?.indexPath(for: broadcast) {
if let index = dataSource?.indexPath(for: message) {
table.scrollToRow(at: index, at: .top, animated: true)
}

sender.isEnabled = true

textField.text = ""
}
}
Expand All @@ -141,13 +217,15 @@ extension ChatViewController {

func update(_ cell: ChatTableViewCell, for message: HMSMessage) {

var name = message.sender
var name = message.sender?.name
var isLocal = false

if let room = interactor?.hmsSDK?.room, let peer = HMSUtilities.getPeer(for: message.sender, in: room) {
if let peer = message.sender {
name = peer.name
isLocal = (peer.peerID == interactor?.hmsSDK?.localPeer?.peerID)
}

guard let name = name else { return }

if isLocal {
cell.nameLabel.textAlignment = .right
Expand All @@ -157,9 +235,35 @@ extension ChatViewController {
cell.messageLabel.textAlignment = .left
}

cell.nameLabel.text = name
let attributedString = NSMutableAttributedString(string: name, attributes: [.foregroundColor: UIColor.link])

if let attributedSender = getSender(message) {
attributedString.append(attributedSender)
}

cell.nameLabel.attributedText = attributedString
cell.messageLabel.text = message.message
}

func getSender(_ message: HMSMessage) -> NSAttributedString? {
let attributes = [ NSAttributedString.Key.foregroundColor: UIColor.black,
NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .body)]

switch message.recipient.type {
case .peer:
if let name = message.recipient.peerRecipient?.name {
return NSAttributedString(string: " (to \(name))", attributes: attributes)
}
fallthrough
case .roles:
if let role = message.recipient.rolesRecipient?.first {
return NSAttributedString(string: " (to \(role.name))", attributes: attributes)
}
fallthrough
default:
return nil
}
}

func applySnapshot(animatingDifferences: Bool = true) {

Expand Down
14 changes: 12 additions & 2 deletions Example/HMSSDKExample/Meeting/HMSSDKInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ final class HMSSDKInteractor: HMSUpdateListener {
internal var hmsSDK: HMSSDK?
internal var onPreview: ((HMSRoom, [HMSTrack]) -> Void)?
internal var onRoleChange: ((HMSRoleChangeRequest) -> Void)?
internal var onChangeTrackState: ((HMSChangeTrackStateRequest) -> Void)?
internal var onRemovedFromRoom: ((HMSRemovedFromRoomNotification) -> Void)?

// MARK: - Instance Properties

Expand Down Expand Up @@ -88,7 +90,7 @@ final class HMSSDKInteractor: HMSUpdateListener {
func accept(changeRole request: HMSRoleChangeRequest) {
hmsSDK?.accept(changeRole: request)
}

// MARK: - HMSSDK Update Callbacks

func on(join room: HMSRoom) {
Expand Down Expand Up @@ -130,7 +132,7 @@ final class HMSSDKInteractor: HMSUpdateListener {

messages.append(message)
NotificationCenter.default.post(name: Constants.messageReceived, object: nil)
Utilities.showToast(message: "💬 \(message.sender) sent you a message")
Utilities.showToast(message: "💬 \(message.sender!.name) sent you a message")
}

func on(updated speakers: [HMSSpeaker]) {
Expand All @@ -152,6 +154,14 @@ final class HMSSDKInteractor: HMSUpdateListener {
func onReconnected() {
print(#function, "Reconnected")
}

func on(changeTrackStateRequest: HMSChangeTrackStateRequest) {
onChangeTrackState?(changeTrackStateRequest)
}

func on(removedFromRoom notification: HMSRemovedFromRoomNotification) {
onRemovedFromRoom?(notification)
}
}

extension HMSSDKInteractor: HMSPreviewListener {
Expand Down
Loading

0 comments on commit 8eeb65c

Please sign in to comment.