mirror of
https://github.com/MessageKit/MessageKit.git
synced 2026-02-06 19:03:19 +00:00
Subclass InputBarView to allow picking images
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
032A15DD25965D9A00E00FE3 /* AlertService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032A15DC25965D9A00E00FE3 /* AlertService.swift */; };
|
||||
032A15E225965E1100E00FE3 /* CameraInputBarAccessoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032A15E125965E1100E00FE3 /* CameraInputBarAccessoryView.swift */; };
|
||||
13CCA04625793058005C19BB /* MessageKit in Frameworks */ = {isa = PBXBuildFile; productRef = 13CCA04525793058005C19BB /* MessageKit */; };
|
||||
13CCA06325793E24005C19BB /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 13CCA06225793E24005C19BB /* Kingfisher */; };
|
||||
1C5433DD24C389C300A5383B /* MessagesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5433DC24C389C300A5383B /* MessagesView.swift */; };
|
||||
@@ -62,6 +64,8 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
032A15DC25965D9A00E00FE3 /* AlertService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertService.swift; sourceTree = "<group>"; };
|
||||
032A15E125965E1100E00FE3 /* CameraInputBarAccessoryView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraInputBarAccessoryView.swift; sourceTree = "<group>"; };
|
||||
13CCA04225793002005C19BB /* MessageKit */ = {isa = PBXFileReference; lastKnownFileType = folder; path = MessageKit; sourceTree = "<group>"; };
|
||||
1C5433DC24C389C300A5383B /* MessagesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagesView.swift; sourceTree = "<group>"; };
|
||||
1C5433DE24C38DBF00A5383B /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
|
||||
@@ -147,6 +151,7 @@
|
||||
1C5433E024C3A32400A5383B /* SwiftUI */,
|
||||
385C2920211FF32E0010B4BA /* CustomCell.swift */,
|
||||
385C2921211FF32E0010B4BA /* TableViewCells.swift */,
|
||||
032A15E125965E1100E00FE3 /* CameraInputBarAccessoryView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
@@ -175,6 +180,7 @@
|
||||
385C292A211FF3450010B4BA /* Settings+UserDefaults.swift */,
|
||||
385C292F211FF3630010B4BA /* UIColor+Extensions.swift */,
|
||||
385C2930211FF3630010B4BA /* UIViewController+Extensions.swift */,
|
||||
032A15DC25965D9A00E00FE3 /* AlertService.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
@@ -516,6 +522,7 @@
|
||||
385C2932211FF3630010B4BA /* UIViewController+Extensions.swift in Sources */,
|
||||
385C292B211FF3450010B4BA /* Settings+UserDefaults.swift in Sources */,
|
||||
385C2945211FF38F0010B4BA /* NavigationController.swift in Sources */,
|
||||
032A15DD25965D9A00E00FE3 /* AlertService.swift in Sources */,
|
||||
385C2948211FF38F0010B4BA /* ChatViewController.swift in Sources */,
|
||||
385C2944211FF38F0010B4BA /* MessageContainerController.swift in Sources */,
|
||||
383B9EB32172A1C4008AB91A /* MockUser.swift in Sources */,
|
||||
@@ -525,6 +532,7 @@
|
||||
1C5433DD24C389C300A5383B /* MessagesView.swift in Sources */,
|
||||
882B5E811CF7D53600B6E160 /* AppDelegate.swift in Sources */,
|
||||
385C292D211FF3520010B4BA /* CustomMessageFlowLayout.swift in Sources */,
|
||||
032A15E225965E1100E00FE3 /* CameraInputBarAccessoryView.swift in Sources */,
|
||||
38CCCC592258419300DD5482 /* AutocompleteExampleViewController.swift in Sources */,
|
||||
63ECDAC2241889630016C349 /* MessageSubviewContainerViewController.swift in Sources */,
|
||||
);
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// AlertService.swift
|
||||
// ChatExample
|
||||
//
|
||||
// Created by Mohannad on 12/25/20.
|
||||
// Copyright © 2020 MessageKit. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
|
||||
class AlertService {
|
||||
|
||||
|
||||
static func showAlert(style: UIAlertController.Style, title: String?, message: String?, actions: [UIAlertAction] = [UIAlertAction(title: "Ok", style: .cancel, handler: nil)], completion: (() -> Swift.Void)? = nil) {
|
||||
let alert = UIAlertController(title: title, message: message, preferredStyle: style)
|
||||
for action in actions {
|
||||
alert.addAction(action)
|
||||
}
|
||||
if let topVC = UIApplication.getTopMostViewController() {
|
||||
alert.popoverPresentationController?.sourceView = topVC.view
|
||||
alert.popoverPresentationController?.sourceRect = CGRect(x: topVC.view.bounds.midX, y: topVC.view.bounds.midY, width: 0, height: 0)
|
||||
alert.popoverPresentationController?.permittedArrowDirections = []
|
||||
topVC.present(alert, animated: true, completion: completion)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
extension UIApplication {
|
||||
class func getTopMostViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
|
||||
if let nav = base as? UINavigationController {
|
||||
return getTopMostViewController(base: nav.visibleViewController)
|
||||
}
|
||||
if let tab = base as? UITabBarController {
|
||||
if let selected = tab.selectedViewController {
|
||||
return getTopMostViewController(base: selected)
|
||||
}
|
||||
}
|
||||
if let presented = base?.presentedViewController {
|
||||
return getTopMostViewController(base: presented)
|
||||
}
|
||||
return base
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "camera.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 101 KiB |
@@ -105,7 +105,16 @@ final class AdvancedExampleViewController: ChatViewController {
|
||||
}
|
||||
|
||||
override func configureMessageInputBar() {
|
||||
super.configureMessageInputBar()
|
||||
//super.configureMessageInputBar()
|
||||
|
||||
messageInputBar = CameraInputBarAccessoryView()
|
||||
messageInputBar.delegate = self
|
||||
messageInputBar.inputTextView.tintColor = .primaryColor
|
||||
messageInputBar.sendButton.setTitleColor(.primaryColor, for: .normal)
|
||||
messageInputBar.sendButton.setTitleColor(
|
||||
UIColor.primaryColor.withAlphaComponent(0.3),
|
||||
for: .highlighted)
|
||||
|
||||
|
||||
messageInputBar.isTranslucent = true
|
||||
messageInputBar.separatorLine.isHidden = true
|
||||
@@ -439,3 +448,28 @@ extension AdvancedExampleViewController: MessagesLayoutDelegate {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
extension AdvancedExampleViewController: CameraInputBarAccessoryViewDelegate {
|
||||
|
||||
func inputBar(_ inputBar: InputBarAccessoryView, didPressSendButtonWith attachments: [AttachmentManager.Attachment]) {
|
||||
|
||||
|
||||
for item in attachments {
|
||||
if case .image(let image) = item {
|
||||
|
||||
self.sendImageMessage(photo: image)
|
||||
}
|
||||
}
|
||||
inputBar.invalidatePlugins()
|
||||
}
|
||||
|
||||
|
||||
func sendImageMessage( photo : UIImage) {
|
||||
|
||||
let photoMessage = MockMessage(image: photo, user: self.currentSender() as! MockUser, messageId: UUID().uuidString, date: Date())
|
||||
self.insertMessage(photoMessage)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
//
|
||||
// CameraInput.swift
|
||||
// ChatExample
|
||||
//
|
||||
// Created by Mohannad on 12/25/20.
|
||||
// Copyright © 2020 MessageKit. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import InputBarAccessoryView
|
||||
|
||||
protocol CameraInputBarAccessoryViewDelegate : InputBarAccessoryViewDelegate {
|
||||
func inputBar(_ inputBar: InputBarAccessoryView, didPressSendButtonWith attachments: [AttachmentManager.Attachment])
|
||||
}
|
||||
|
||||
extension CameraInputBarAccessoryViewDelegate {
|
||||
|
||||
func inputBar(_ inputBar: InputBarAccessoryView, didPressSendButtonWith attachments: [AttachmentManager.Attachment]){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CameraInputBarAccessoryView: InputBarAccessoryView {
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
configure()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
lazy var attachmentManager: AttachmentManager = { [unowned self] in
|
||||
let manager = AttachmentManager()
|
||||
manager.delegate = self
|
||||
return manager
|
||||
}()
|
||||
|
||||
func configure(){
|
||||
let camera = makeButton(named: "camera")
|
||||
camera.tintColor = .darkGray
|
||||
camera.onTouchUpInside { (item) in
|
||||
self.showImagePickerControllerActionSheet()
|
||||
}
|
||||
self.setLeftStackViewWidthConstant(to: 35, animated: true)
|
||||
self.setStackViewItems([camera], forStack: .left, animated: false)
|
||||
self.inputPlugins = [attachmentManager]
|
||||
|
||||
}
|
||||
|
||||
override func didSelectSendButton() {
|
||||
|
||||
if attachmentManager.attachments.count > 0 {
|
||||
|
||||
(delegate as? CameraInputBarAccessoryViewDelegate)?.inputBar(self, didPressSendButtonWith: attachmentManager.attachments)
|
||||
}
|
||||
else {
|
||||
|
||||
delegate?.inputBar(self, didPressSendButtonWith: inputTextView.text)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private func makeButton(named: String) -> InputBarButtonItem {
|
||||
return InputBarButtonItem()
|
||||
.configure {
|
||||
$0.spacing = .fixed(10)
|
||||
$0.image = UIImage(named: named)?.withRenderingMode(.alwaysTemplate)
|
||||
$0.setSize(CGSize(width: 30, height: 30), animated: false)
|
||||
}.onSelected {
|
||||
$0.tintColor = .systemBlue
|
||||
}.onDeselected {
|
||||
$0.tintColor = UIColor.lightGray
|
||||
}.onTouchUpInside { _ in
|
||||
print("Item Tapped")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
extension CameraInputBarAccessoryView : UIImagePickerControllerDelegate , UINavigationControllerDelegate {
|
||||
|
||||
@objc func showImagePickerControllerActionSheet() {
|
||||
|
||||
|
||||
let photoLibraryAction = UIAlertAction(title: "Choose From Library", style: .default) { (action) in
|
||||
self.showImagePickerController(sourceType: .photoLibrary)
|
||||
}
|
||||
|
||||
let cameraAction = UIAlertAction(title: "Take From Camera", style: .default) { (action) in
|
||||
self.showImagePickerController(sourceType: .camera)
|
||||
}
|
||||
|
||||
let cancelAction = UIAlertAction(title: "Cancel", style: .default , handler: nil)
|
||||
|
||||
AlertService.showAlert(style: .actionSheet, title: "Choose Your Image", message: nil, actions: [photoLibraryAction, cameraAction , cancelAction], completion: nil)
|
||||
}
|
||||
|
||||
func showImagePickerController(sourceType: UIImagePickerController.SourceType){
|
||||
|
||||
let imgPicker = UIImagePickerController()
|
||||
imgPicker.delegate = self
|
||||
imgPicker.allowsEditing = true
|
||||
imgPicker.sourceType = sourceType
|
||||
inputAccessoryView?.isHidden = true
|
||||
getRootViewController()?.present(imgPicker, animated: true, completion: nil)
|
||||
|
||||
}
|
||||
|
||||
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
|
||||
|
||||
if let editedImage = info[ UIImagePickerController.InfoKey.editedImage] as? UIImage {
|
||||
// self.sendImageMessage(photo: editedImage)
|
||||
self.inputPlugins.forEach { _ = $0.handleInput(of: editedImage)}
|
||||
|
||||
}
|
||||
else if let originImage = info[ UIImagePickerController.InfoKey.originalImage] as? UIImage {
|
||||
|
||||
self.inputPlugins.forEach { _ = $0.handleInput(of: originImage)}
|
||||
//self.sendImageMessage(photo: originImage)
|
||||
}
|
||||
getRootViewController()?.dismiss(animated: true, completion: nil)
|
||||
inputAccessoryView?.isHidden = false
|
||||
|
||||
}
|
||||
|
||||
|
||||
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
|
||||
getRootViewController()?.dismiss(animated: true, completion: nil)
|
||||
inputAccessoryView?.isHidden = false
|
||||
}
|
||||
|
||||
|
||||
func getRootViewController() -> UIViewController? {
|
||||
return (UIApplication.shared.delegate as? AppDelegate)?.window?.rootViewController
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
extension CameraInputBarAccessoryView: AttachmentManagerDelegate {
|
||||
|
||||
|
||||
// MARK: - AttachmentManagerDelegate
|
||||
|
||||
func attachmentManager(_ manager: AttachmentManager, shouldBecomeVisible: Bool) {
|
||||
setAttachmentManager(active: shouldBecomeVisible)
|
||||
}
|
||||
|
||||
func attachmentManager(_ manager: AttachmentManager, didReloadTo attachments: [AttachmentManager.Attachment]) {
|
||||
self.sendButton.isEnabled = manager.attachments.count > 0
|
||||
}
|
||||
|
||||
func attachmentManager(_ manager: AttachmentManager, didInsert attachment: AttachmentManager.Attachment, at index: Int) {
|
||||
self.sendButton.isEnabled = manager.attachments.count > 0
|
||||
}
|
||||
|
||||
func attachmentManager(_ manager: AttachmentManager, didRemove attachment: AttachmentManager.Attachment, at index: Int) {
|
||||
self.sendButton.isEnabled = manager.attachments.count > 0
|
||||
}
|
||||
|
||||
func attachmentManager(_ manager: AttachmentManager, didSelectAddAttachmentAt index: Int) {
|
||||
self.showImagePickerControllerActionSheet()
|
||||
}
|
||||
|
||||
// MARK: - AttachmentManagerDelegate Helper
|
||||
|
||||
func setAttachmentManager(active: Bool) {
|
||||
|
||||
let topStackView = self.topStackView
|
||||
if active && !topStackView.arrangedSubviews.contains(attachmentManager.attachmentView) {
|
||||
topStackView.insertArrangedSubview(attachmentManager.attachmentView, at: topStackView.arrangedSubviews.count)
|
||||
topStackView.layoutIfNeeded()
|
||||
} else if !active && topStackView.arrangedSubviews.contains(attachmentManager.attachmentView) {
|
||||
topStackView.removeArrangedSubview(attachmentManager.attachmentView)
|
||||
topStackView.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user