mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 11:08:06 +00:00
Add reactions list in bottom sheet
This commit is contained in:
parent
3a065eaac8
commit
1c2b726016
5 changed files with 212 additions and 49 deletions
|
|
@ -383,6 +383,18 @@ class ChatConversationTableViewSwift: UIViewController, UICollectionViewDataSour
|
|||
cell.myEmojisView.isHidden = false
|
||||
cell.myImageView.isHidden = true
|
||||
cell.optionLabel.isHidden = true
|
||||
|
||||
cell.myEmojiButton1.layer.cornerRadius = 10
|
||||
cell.myEmojiButton1.backgroundColor = VoipTheme.light_grey_color
|
||||
cell.myEmojiButton2.layer.cornerRadius = 10
|
||||
cell.myEmojiButton2.backgroundColor = VoipTheme.light_grey_color
|
||||
cell.myEmojiButton3.layer.cornerRadius = 10
|
||||
cell.myEmojiButton3.backgroundColor = VoipTheme.light_grey_color
|
||||
cell.myEmojiButton4.layer.cornerRadius = 10
|
||||
cell.myEmojiButton4.backgroundColor = VoipTheme.light_grey_color
|
||||
cell.myEmojiButton5.layer.cornerRadius = 10
|
||||
cell.myEmojiButton5.backgroundColor = VoipTheme.light_grey_color
|
||||
|
||||
cell.myEmojiButton1.onClick {
|
||||
do {
|
||||
let messageReaction = try message.createReaction(utf8Reaction: "❤️")
|
||||
|
|
|
|||
|
|
@ -36,34 +36,44 @@
|
|||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" id="zqz-hc-78g" userLabel="emoji1">
|
||||
<rect key="frame" x="5" y="18" width="47" height="35"/>
|
||||
<rect key="frame" x="10" y="25" width="35" height="35"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<buttonConfiguration key="configuration" style="plain" title="❤️"/>
|
||||
<buttonConfiguration key="configuration" style="plain" title="❤️" buttonSize="large">
|
||||
<directionalEdgeInsets key="contentInsets" top="0.0" leading="3" bottom="0.0" trailing="0.0"/>
|
||||
</buttonConfiguration>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" id="MZ1-PD-4wS" userLabel="emoji2">
|
||||
<rect key="frame" x="77" y="18" width="47" height="35"/>
|
||||
<rect key="frame" x="84" y="25" width="35" height="35"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<buttonConfiguration key="configuration" style="plain" title="👍"/>
|
||||
<buttonConfiguration key="configuration" style="plain" title="👍" buttonSize="large">
|
||||
<directionalEdgeInsets key="contentInsets" top="0.0" leading="3" bottom="0.0" trailing="0.0"/>
|
||||
</buttonConfiguration>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" id="4hz-YC-t5L" userLabel="emoji3">
|
||||
<rect key="frame" x="151" y="18" width="47" height="35"/>
|
||||
<rect key="frame" x="158" y="25" width="35" height="35"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<buttonConfiguration key="configuration" style="plain" title="😂"/>
|
||||
<buttonConfiguration key="configuration" style="plain" title="😂" buttonSize="large">
|
||||
<directionalEdgeInsets key="contentInsets" top="0.0" leading="3" bottom="0.0" trailing="0.0"/>
|
||||
</buttonConfiguration>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" id="rVf-gM-dFu" userLabel="emoji4">
|
||||
<rect key="frame" x="225" y="18" width="47" height="35"/>
|
||||
<rect key="frame" x="231" y="25" width="35" height="35"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<buttonConfiguration key="configuration" style="plain" title="😮"/>
|
||||
<buttonConfiguration key="configuration" style="plain" title="😮" buttonSize="large">
|
||||
<directionalEdgeInsets key="contentInsets" top="0.0" leading="3" bottom="0.0" trailing="0.0"/>
|
||||
</buttonConfiguration>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" id="Jif-0X-Jwc" userLabel="emoji5">
|
||||
<rect key="frame" x="298" y="18" width="47" height="35"/>
|
||||
<rect key="frame" x="305" y="25" width="35" height="35"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<buttonConfiguration key="configuration" style="plain" title="😢"/>
|
||||
<buttonConfiguration key="configuration" style="plain" title="😢" buttonSize="large">
|
||||
<directionalEdgeInsets key="contentInsets" top="0.0" leading="3" bottom="0.0" trailing="0.0"/>
|
||||
</buttonConfiguration>
|
||||
</button>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="cIf-Td-6PX"/>
|
||||
|
|
|
|||
77
Classes/Swift/Chat/Views/Fragments/ReactionCell.swift
Normal file
77
Classes/Swift/Chat/Views/Fragments/ReactionCell.swift
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
import UIKit
|
||||
import Foundation
|
||||
import SnapKit
|
||||
import linphonesw
|
||||
|
||||
class ReactionCell: UITableViewCell {
|
||||
|
||||
// Layout Constants
|
||||
static let cell_height = 50.0
|
||||
let avatar_left_margin = 15.0
|
||||
let texts_left_margin = 15.0
|
||||
let avatar_size = 35.0
|
||||
|
||||
let avatar = Avatar(color:VoipTheme.primaryTextColor, textStyle: VoipTheme.call_generated_avatar_small)
|
||||
let displayName = StyledLabel(VoipTheme.conference_participant_name_font)
|
||||
let displayEmoji = StyledLabel(VoipTheme.conference_participant_name_font)
|
||||
|
||||
|
||||
var owningParticpantsListView : ParticipantsListView? = nil
|
||||
|
||||
var reactionData: ChatMessageReaction? = nil {
|
||||
didSet {
|
||||
if let data = reactionData {
|
||||
avatar.fillFromAddress(address: data.fromAddress!)
|
||||
displayName.text = data.fromAddress!.addressBookEnhancedDisplayName()
|
||||
displayEmoji.text = data.body
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
contentView.height(ReactionCell.cell_height).matchParentSideBorders().done()
|
||||
|
||||
addSubview(avatar)
|
||||
avatar.size(w: avatar_size, h: avatar_size).centerY().alignParentLeft(withMargin: avatar_left_margin).done()
|
||||
|
||||
// Name Address
|
||||
|
||||
let nameAddress = UIStackView()
|
||||
nameAddress.addArrangedSubview(displayName)
|
||||
nameAddress.axis = .vertical
|
||||
addSubview(nameAddress)
|
||||
nameAddress.toRightOf(avatar,withLeftMargin:texts_left_margin).centerY().done()
|
||||
|
||||
|
||||
addSubview(displayEmoji)
|
||||
displayEmoji.alignParentRight(withMargin: avatar_left_margin*2).centerY().done()
|
||||
|
||||
contentView.backgroundColor = .clear
|
||||
backgroundColor = .clear
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
|
@ -35,7 +35,19 @@ final class SheetViewController: UIViewController {
|
|||
private var currentPosition = 0
|
||||
private var tabStyle = SlidingTabStyle.fixed
|
||||
private let heightHeader = 40
|
||||
|
||||
var chatMessage : ChatMessage
|
||||
|
||||
/// Put your custom argument labels here, not inside the `required init?`
|
||||
init(chatMessageInit: ChatMessage) {
|
||||
self.chatMessage = chatMessageInit
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
/// This is in case the View Controller is loaded from the Storyboard
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setupUI()
|
||||
|
|
@ -43,24 +55,45 @@ final class SheetViewController: UIViewController {
|
|||
|
||||
private func setupUI(){
|
||||
// view
|
||||
view.backgroundColor = .white
|
||||
view.backgroundColor = VoipTheme.voipBackgroundBWColor.get()
|
||||
|
||||
navigationController?.navigationBar.barTintColor = .orange
|
||||
navigationController?.navigationBar.isTranslucent = false
|
||||
navigationController?.navigationBar.shadowImage = UIImage()
|
||||
navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
|
||||
navigationController?.navigationBar.barStyle = .black
|
||||
|
||||
// slidingTab
|
||||
addItem(item: SimpleItemViewControllerOne(), title: "REACTIONS")
|
||||
addItem(item: SimpleItemViewControllerOne(), title: "❤️")
|
||||
addItem(item: SimpleItemViewControllerOne(), title: "👍")
|
||||
addItem(item: SimpleItemViewControllerOne(), title: "😂")
|
||||
addItem(item: SimpleItemViewControllerOne(), title: "😮")
|
||||
addItem(item: SimpleItemViewControllerOne(), title: "😢")
|
||||
setHeaderActiveColor(color: .orange) // default blue
|
||||
setStyle(style: .fixed) // default fixed
|
||||
build()
|
||||
|
||||
if chatMessage.reactions.count <= 1 {
|
||||
addItem(item: SimpleItemViewController(chatMessageReactionsListInit: chatMessage.reactions), title: "\(chatMessage.reactions.count) REACTION")
|
||||
} else {
|
||||
addItem(item: SimpleItemViewController(chatMessageReactionsListInit: chatMessage.reactions), title: "\(chatMessage.reactions.count) REACTIONS")
|
||||
}
|
||||
|
||||
let reaction1Count = chatMessage.reactions.filter({$0.body == "❤️"}).count
|
||||
let reaction2Count = chatMessage.reactions.filter({$0.body == "👍"}).count
|
||||
let reaction3Count = chatMessage.reactions.filter({$0.body == "😂"}).count
|
||||
let reaction4Count = chatMessage.reactions.filter({$0.body == "😮"}).count
|
||||
let reaction5Count = chatMessage.reactions.filter({$0.body == "😢"}).count
|
||||
|
||||
if reaction1Count > 0 {
|
||||
addItem(item: SimpleItemViewController(chatMessageReactionsListInit: chatMessage.reactions.filter({$0.body == "❤️"})), title: "❤️ \(reaction1Count)")
|
||||
}
|
||||
if reaction2Count > 0 {
|
||||
addItem(item: SimpleItemViewController(chatMessageReactionsListInit: chatMessage.reactions.filter({$0.body == "👍"})), title: "👍 \(reaction2Count)")
|
||||
}
|
||||
if reaction3Count > 0 {
|
||||
addItem(item: SimpleItemViewController(chatMessageReactionsListInit: chatMessage.reactions.filter({$0.body == "😂"})), title: "😂 \(reaction3Count)")
|
||||
}
|
||||
if reaction4Count > 0 {
|
||||
addItem(item: SimpleItemViewController(chatMessageReactionsListInit: chatMessage.reactions.filter({$0.body == "😮"})), title: "😮 \(reaction4Count)")
|
||||
}
|
||||
if reaction5Count > 0 {
|
||||
addItem(item: SimpleItemViewController(chatMessageReactionsListInit: chatMessage.reactions.filter({$0.body == "😢"})), title: "😢 \(reaction5Count)")
|
||||
}
|
||||
|
||||
setHeaderActiveColor(color: .orange) // default blue
|
||||
setStyle(style: .fixed) // default fixed
|
||||
build()
|
||||
}
|
||||
|
||||
func addItem(item: UIViewController, title: String){
|
||||
|
|
@ -108,13 +141,13 @@ final class SheetViewController: UIViewController {
|
|||
|
||||
// collectionHeader
|
||||
collectionHeader.translatesAutoresizingMaskIntoConstraints = false
|
||||
collectionHeader.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40).isActive = true
|
||||
collectionHeader.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
|
||||
collectionHeader.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
|
||||
collectionHeader.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
|
||||
collectionHeader.heightAnchor.constraint(equalToConstant: CGFloat(heightHeader)).isActive = true
|
||||
(collectionHeader.collectionViewLayout as? UICollectionViewFlowLayout)?.scrollDirection = .horizontal
|
||||
collectionHeader.showsHorizontalScrollIndicator = false
|
||||
collectionHeader.backgroundColor = colorHeaderBackground
|
||||
collectionHeader.backgroundColor = VoipTheme.voipBackgroundBWColor.get()
|
||||
collectionHeader.register(HeaderCell.self, forCellWithReuseIdentifier: collectionHeaderIdentifier)
|
||||
collectionHeader.delegate = self
|
||||
collectionHeader.dataSource = self
|
||||
|
|
@ -126,7 +159,7 @@ final class SheetViewController: UIViewController {
|
|||
collectionPage.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
|
||||
collectionPage.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
|
||||
collectionPage.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
|
||||
collectionPage.backgroundColor = .white
|
||||
collectionPage.backgroundColor = VoipTheme.voipBackgroundBWColor.get()
|
||||
collectionPage.showsHorizontalScrollIndicator = false
|
||||
(collectionPage.collectionViewLayout as? UICollectionViewFlowLayout)?.scrollDirection = .horizontal
|
||||
collectionPage.isPagingEnabled = true
|
||||
|
|
@ -144,6 +177,11 @@ final class SheetViewController: UIViewController {
|
|||
var text: String! {
|
||||
didSet {
|
||||
label.text = text
|
||||
if label.text!.contains("REACTIONS") {
|
||||
label.font = UIFont.boldSystemFont(ofSize: 8)
|
||||
} else {
|
||||
label.font = UIFont.boldSystemFont(ofSize: 14)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -177,7 +215,7 @@ final class SheetViewController: UIViewController {
|
|||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
|
||||
label.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
|
||||
label.font = UIFont.boldSystemFont(ofSize: 8)
|
||||
label.font = UIFont.boldSystemFont(ofSize: 14)
|
||||
|
||||
// indicator
|
||||
indicator.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
|
@ -272,10 +310,22 @@ enum SlidingTabStyle: String {
|
|||
case flexible
|
||||
}
|
||||
|
||||
class SimpleItemViewControllerOne: UIViewController{
|
||||
|
||||
private let label = UILabel()
|
||||
|
||||
class SimpleItemViewController: UIViewController, UITableViewDataSource {
|
||||
|
||||
let reactionsListTableView = UITableView()
|
||||
var chatMessageReactionsList : [ChatMessageReaction] = []
|
||||
|
||||
init(chatMessageReactionsListInit: [ChatMessageReaction]) {
|
||||
self.chatMessageReactionsList = chatMessageReactionsListInit
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
/// This is in case the View Controller is loaded from the Storyboard
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setupUI()
|
||||
|
|
@ -283,14 +333,30 @@ class SimpleItemViewControllerOne: UIViewController{
|
|||
|
||||
private func setupUI(){
|
||||
// view
|
||||
view.backgroundColor = .white
|
||||
view.addSubview(label)
|
||||
|
||||
// label
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
|
||||
label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
|
||||
label.text = "First Controller"
|
||||
view.backgroundColor = VoipTheme.voipBackgroundBWColor.get()
|
||||
|
||||
// ParticipantsList
|
||||
view.addSubview(reactionsListTableView)
|
||||
//reactionsListTableView.matchParentDimmensions().done()
|
||||
reactionsListTableView.alignParentTop(withMargin: 10).alignParentBottom().alignParentLeft().alignParentRight().done()
|
||||
reactionsListTableView.dataSource = self
|
||||
reactionsListTableView.register(ReactionCell.self, forCellReuseIdentifier: "ReactionCell")
|
||||
reactionsListTableView.allowsSelection = false
|
||||
if #available(iOS 15.0, *) {
|
||||
reactionsListTableView.allowsFocus = false
|
||||
}
|
||||
reactionsListTableView.separatorStyle = .singleLine
|
||||
reactionsListTableView.separatorColor = .white
|
||||
}
|
||||
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return chatMessageReactionsList.count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell:ReactionCell = tableView.dequeueReusableCell(withIdentifier: "ReactionCell") as! ReactionCell
|
||||
cell.selectionStyle = .none
|
||||
cell.reactionData = chatMessageReactionsList[indexPath.row]
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1461,41 +1461,39 @@ class MultilineMessageCell: SwipeCollectionViewCell, UICollectionViewDataSource,
|
|||
|
||||
chatRead.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -16).isActive = true
|
||||
|
||||
var reactionCount = 0
|
||||
event.chatMessage!.reactions.forEach { chatMessageReaction in
|
||||
reactionCount += 1
|
||||
switch chatMessageReaction.body {
|
||||
case "❤️":
|
||||
if stackViewReactionsItem1.isHidden == false {
|
||||
stackViewReactionsCounter.text = String(reactionCount)
|
||||
stackViewReactionsCounter.text = String(event.chatMessage!.reactions.count)
|
||||
stackViewReactionsCounter.isHidden = false
|
||||
} else {
|
||||
stackViewReactionsItem1.isHidden = false
|
||||
}
|
||||
case "👍":
|
||||
if stackViewReactionsItem2.isHidden == false {
|
||||
stackViewReactionsCounter.text = String(reactionCount)
|
||||
stackViewReactionsCounter.text = String(event.chatMessage!.reactions.count)
|
||||
stackViewReactionsCounter.isHidden = false
|
||||
} else {
|
||||
stackViewReactionsItem2.isHidden = false
|
||||
}
|
||||
case "😂":
|
||||
if stackViewReactionsItem3.isHidden == false {
|
||||
stackViewReactionsCounter.text = String(reactionCount)
|
||||
stackViewReactionsCounter.text = String(event.chatMessage!.reactions.count)
|
||||
stackViewReactionsCounter.isHidden = false
|
||||
} else {
|
||||
stackViewReactionsItem3.isHidden = false
|
||||
}
|
||||
case "😮":
|
||||
if stackViewReactionsItem4.isHidden == false {
|
||||
stackViewReactionsCounter.text = String(reactionCount)
|
||||
stackViewReactionsCounter.text = String(event.chatMessage!.reactions.count)
|
||||
stackViewReactionsCounter.isHidden = false
|
||||
} else {
|
||||
stackViewReactionsItem4.isHidden = false
|
||||
}
|
||||
case "😢":
|
||||
if stackViewReactionsItem5.isHidden == false {
|
||||
stackViewReactionsCounter.text = String(reactionCount)
|
||||
stackViewReactionsCounter.text = String(event.chatMessage!.reactions.count)
|
||||
stackViewReactionsCounter.isHidden = false
|
||||
} else {
|
||||
stackViewReactionsItem5.isHidden = false
|
||||
|
|
@ -1577,9 +1575,9 @@ class MultilineMessageCell: SwipeCollectionViewCell, UICollectionViewDataSource,
|
|||
|
||||
@objc func showMyViewControllerInACustomizedSheet(_ sender: UITapGestureRecognizer? = nil) {
|
||||
if #available(iOS 15.0, *) {
|
||||
let sheetViewController = SheetViewController()
|
||||
let sheetViewController = SheetViewController(chatMessageInit: chatMessage!)
|
||||
if let sheetController = sheetViewController.sheetPresentationController {
|
||||
sheetController.detents = [.medium()]
|
||||
sheetController.detents = [.medium()]
|
||||
sheetController.prefersGrabberVisible = true
|
||||
}
|
||||
PhoneMainView.instance()!.present(sheetViewController, animated: true, completion: nil)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue