sendbird-uikit-ios/Sources/View/ChannelList/SBUGroupChannelListViewCont...

405 lines
16 KiB
Swift

//
// SBUGroupChannelListViewController.swift
// SendbirdUIKit
//
// Created by Tez Park on 03/02/2020.
// Copyright © 2020 Sendbird, Inc. All rights reserved.
//
import UIKit
import SendbirdChatSDK
@objcMembers
open class SBUGroupChannelListViewController: SBUBaseChannelListViewController, SBUGroupChannelListModuleHeaderDelegate, SBUGroupChannelListModuleListDelegate, SBUGroupChannelListModuleListDataSource, SBUCreateChannelTypeSelectorDelegate, SBUCommonViewModelDelegate, SBUGroupChannelListViewModelDelegate {
// MARK: - UI Properties (Public)
public var headerComponent: SBUGroupChannelListModule.Header? {
get { self.baseHeaderComponent as? SBUGroupChannelListModule.Header }
set { self.baseHeaderComponent = newValue }
}
public var listComponent: SBUGroupChannelListModule.List? {
get { self.baseListComponent as? SBUGroupChannelListModule.List }
set { self.baseListComponent = newValue }
}
@SBUThemeWrapper(theme: SBUTheme.groupChannelListTheme)
public var theme: SBUGroupChannelListTheme
public lazy var createChannelTypeSelector: UIView? = nil
// MARK: - UI properties (Private)
private lazy var defaultCreateChannelTypeSelector: SBUCreateChannelTypeSelector = {
let view = SBUCreateChannelTypeSelector(delegate: self)
view.isHidden = true
return view
}()
// MARK: - Logic properties (Public)
public var viewModel: SBUGroupChannelListViewModel? {
get { self.baseViewModel as? SBUGroupChannelListViewModel }
set { self.baseViewModel = newValue }
}
/// This object has a list of all channels.
public var channelList: [GroupChannel] { self.viewModel?.channelList ?? [] }
/// This is a property that allows you to show the channel type selector when creating a channel. (default: `true`)
/// - Since: 3.0.0
public var enableCreateChannelTypeSelector: Bool = true
// MARK: - Lifecycle
@available(*, unavailable, renamed: "SBUGroupChannelListViewController()")
required public init?(coder: NSCoder) {
super.init(coder: coder)
fatalError()
}
@available(*, unavailable, renamed: "SBUGroupChannelListViewController()")
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
fatalError()
}
/// This function initialize the class without `channelListQuery`.
public init() {
super.init(nibName: nil, bundle: nil)
self.createViewModel(channelListQuery: nil)
self.headerComponent = SBUModuleSet.groupChannelListModule.headerComponent
self.listComponent = SBUModuleSet.groupChannelListModule.listComponent
}
/// You can initialize the class through this function.
/// If you have `channelListQuery`, please set it. If not set, it is used as default value.
///
/// See the example below for query generation.
/// ```
/// let params = GroupChannelListQueryParams()
/// params.includeEmptyChannel = false
/// params.includeFrozenChannel = true
/// let query = GroupChannel.createMyGroupChannelListQuery(params: params)
/// ...
/// ```
/// - Parameter channelListQuery: Your own `GroupChannelListQuery` object
/// - Since: 1.0.11
required public init(channelListQuery: GroupChannelListQuery? = nil) {
super.init(nibName: nil, bundle: nil)
SBULog.info("")
self.createViewModel(channelListQuery: channelListQuery)
self.headerComponent = SBUModuleSet.groupChannelListModule.headerComponent
self.listComponent = SBUModuleSet.groupChannelListModule.listComponent
}
open override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
self.viewModel?.initChannelList()
}
open override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.updateStyles()
}
open override var preferredStatusBarStyle: UIStatusBarStyle {
self.theme.statusBarStyle
}
deinit {
SBULog.info("")
self.viewModel = nil
self.headerComponent = nil
self.listComponent = nil
}
// MARK: - ViewModel
/// Creates the view model.
/// - Parameter channelListQuery: Customer's own `GroupChannelListQuery` object
/// - Since: 3.0.0
open func createViewModel(channelListQuery: GroupChannelListQuery?) {
self.viewModel = SBUGroupChannelListViewModel(
delegate: self,
channelListQuery: channelListQuery
)
}
// MARK: - Sendbird UIKit Life cycle
open override func setupViews() {
// Header component
self.headerComponent?.configure(delegate: self, theme: self.theme)
// List component
self.listComponent?.configure(delegate: self, dataSource: self, theme: self.theme)
// Channel type selector
self.loadChannelTypeSelector()
super.setupViews()
}
open override func setupLayouts() {
super.setupLayouts()
if let view = self.navigationController?.view,
let createChannelTypeSelector = self.createChannelTypeSelector {
createChannelTypeSelector.sbu_constraint(
equalTo: view,
leading: 0,
trailing: 0,
top: 0,
bottom: 0
)
}
}
open override func setupStyles() {
self.setupNavigationBar(
backgroundColor: self.theme.navigationBarTintColor,
shadowColor: self.theme.navigationBarShadowColor
)
self.headerComponent?.setupStyles(theme: self.theme)
self.listComponent?.setupStyles(theme: self.theme)
if let createChannelTypeSelector = self.createChannelTypeSelector as? SBUCreateChannelTypeSelector {
createChannelTypeSelector.setupStyles()
}
self.view.backgroundColor = theme.backgroundColor
}
open override func updateStyles() {
super.updateStyles()
}
// MARK: - Common
open func loadChannelTypeSelector() {
if SBUAvailable.isSupportSuperGroupChannel() || SBUAvailable.isSupportBroadcastChannel() {
if self.createChannelTypeSelector == nil {
self.createChannelTypeSelector = self.defaultCreateChannelTypeSelector
}
if let createChannelTypeSelector = self.createChannelTypeSelector {
self.navigationController?.view.addSubview(createChannelTypeSelector)
}
}
}
// MARK: - Actions (Show)
/// This is a function that shows the channelViewController.
///
/// If you want to use a custom channelViewController, override it and implement it.
/// - Parameters:
/// - channelURL: channel url for use in channelViewController.
/// - messageListParams: If there is a messageListParams set directly for use in Channel, set it up here
open override func showChannel(channelURL: String, messageListParams: MessageListParams? = nil) {
GroupChannel.getChannel(url: channelURL) { channel, error in
guard error == nil, let channel = channel else { return }
if channel.isChatNotification {
let channelVC = SBUViewControllerSet.ChatNotificationChannelViewController.init(
channel: channel,
notificationListParams: messageListParams,
displaysLocalCachedListFirst: true
)
self.navigationController?.pushViewController(channelVC, animated: true)
} else if channel.isFeedChannel() {
let channelVC = SBUViewControllerSet.FeedNotificationChannelViewController.init(
channelURL: channelURL,
notificationListParams: messageListParams,
displaysLocalCachedListFirst: true
)
self.navigationController?.pushViewController(channelVC, animated: true)
} else {
let channelVC = SBUViewControllerSet.GroupChannelViewController.init(
channelURL: channelURL,
messageListParams: messageListParams,
displaysLocalCachedListFirst: true
)
self.navigationController?.pushViewController(channelVC, animated: true)
}
}
}
/// This is a function that shows the channel type selector when a supergroup/broadcast channel can be set.
/// If it cannot be set, this function shows the channel creation screen.
/// - Since: 3.0.0
open func showCreateChannelOrTypeSelector() {
if (SBUAvailable.isSupportSuperGroupChannel() || SBUAvailable.isSupportBroadcastChannel())
&& self.createChannelTypeSelector != nil
&& self.enableCreateChannelTypeSelector {
self.showCreateChannelTypeSelector()
} else {
self.showCreateChannel(type: .group)
}
}
/// This is a function that shows the channel type selector when a supergroup/broadcast channel can be set.
///
/// * If you want to use a custom `createChannelTypeSelector`, override it and implement it.
/// - note: Type: GroupChannel / SuperGroupChannel / BroadcastChannel
/// - Since: 1.2.0
open func showCreateChannelTypeSelector() {
if let typeSelector = self.createChannelTypeSelector as? SBUCreateChannelTypeSelectorProtocol {
typeSelector.show()
}
}
/// This is a function that shows the channel creation viewController with channel type.
///
/// If you want to use a custom createChannelViewController, override it and implement it.
/// - Parameter type: Using the Specified Type in CreateChannelViewController (default: `.group`)
open func showCreateChannel(type: ChannelCreationType = .group) {
let createChannelVC = SBUViewControllerSet.CreateChannelViewController.init(type: type)
self.navigationController?.pushViewController(createChannelVC, animated: true)
}
// MARK: - Error handling
private func errorHandler(_ error: SBError) {
self.errorHandler(error.localizedDescription, error.code)
}
open override func errorHandler(_ message: String?, _ code: NSInteger? = nil) {
SBULog.error("Did receive error: \(message ?? "")")
}
// MARK: - SBUGroupChannelListModuleHeaderDelegate
open func baseChannelListModule(_ headerComponent: SBUBaseChannelListModule.Header,
didUpdateTitleView titleView: UIView?) {
self.navigationItem.titleView = titleView
}
open func baseChannelListModule(_ headerComponent: SBUBaseChannelListModule.Header,
didUpdateLeftItem leftItem: UIBarButtonItem?) {
self.navigationItem.leftBarButtonItem = leftItem
}
open func baseChannelListModule(_ headerComponent: SBUBaseChannelListModule.Header,
didUpdateRightItem rightItem: UIBarButtonItem?) {
self.navigationItem.rightBarButtonItem = rightItem
}
open func baseChannelListModule(_ headerComponent: SBUBaseChannelListModule.Header,
didTapLeftItem leftItem: UIBarButtonItem) {
self.onClickBack()
}
open func baseChannelListModule(_ headerComponent: SBUBaseChannelListModule.Header,
didTapRightItem rightItem: UIBarButtonItem) {
self.showCreateChannelOrTypeSelector()
}
// MARK: - SBUGroupChannelListModuleListDelegate
open func baseChannelListModule(_ listComponent: SBUBaseChannelListModule.List,
didSelectRowAt indexPath: IndexPath) {
guard self.channelList.count > indexPath.row else { return }
let channel = self.channelList[indexPath.row]
self.showChannel(channelURL: channel.channelURL)
}
open func baseChannelListModule(_ listComponent: SBUBaseChannelListModule.List,
didDetectPreloadingPosition indexPath: IndexPath) {
self.viewModel?.loadNextChannelList(reset: false)
}
open func baseChannelListModuleDidSelectRetry(_ listComponent: SBUBaseChannelListModule.List) {
self.viewModel?.initChannelList()
}
public func baseChannelListModuleDidSelectRefresh(_ listComponent: SBUBaseChannelListModule.List) {
self.viewModel?.loadNextChannelList(reset: true)
}
open func groupChannelListModule(_ listComponent: SBUGroupChannelListModule.List,
didSelectLeave channel: GroupChannel) {
self.viewModel?.leaveChannel(channel)
}
open func groupChannelListModule(_ listComponent: SBUGroupChannelListModule.List,
didChangePushTriggerOption option: GroupChannelPushTriggerOption,
channel: GroupChannel) {
self.viewModel?.changePushTriggerOption(option: option, channel: channel)
}
// MARK: - SBUGroupChannelListModuleListDataSource
open func baseChannelListModule(_ listComponent: SBUBaseChannelListModule.List,
channelsInTableView tableView: UITableView) -> [BaseChannel]? {
return self.channelList
}
// MARK: - SBUCreateChannelTypeSelectorDelegate
open func didSelectCloseSelector() {
if let typeSelector = self.createChannelTypeSelector
as? SBUCreateChannelTypeSelectorProtocol {
typeSelector.dismiss()
}
}
open func didSelectCreateGroupChannel() {
if let typeSelector = self.createChannelTypeSelector
as? SBUCreateChannelTypeSelectorProtocol {
typeSelector.dismiss()
}
self.showCreateChannel(type: .group)
}
open func didSelectCreateSuperGroupChannel() {
if let typeSelector = self.createChannelTypeSelector
as? SBUCreateChannelTypeSelectorProtocol {
typeSelector.dismiss()
}
self.showCreateChannel(type: .supergroup)
}
open func didSelectCreateBroadcastChannel() {
if let typeSelector = self.createChannelTypeSelector
as? SBUCreateChannelTypeSelectorProtocol {
typeSelector.dismiss()
}
self.showCreateChannel(type: .broadcast)
}
// MARK: - SBUCommonViewModelDelegate
open func connectionStateDidChange(_ isConnected: Bool) {
if isConnected {
self.loadChannelTypeSelector()
}
}
open func shouldUpdateLoadingState(_ isLoading: Bool) {
self.showLoading(isLoading)
}
open func didReceiveError(_ error: SBError?, isBlocker: Bool) {
self.showLoading(false)
self.errorHandler(error?.description ?? "")
if isBlocker {
self.viewModel?.reset()
self.listComponent?.updateEmptyView(type: .error)
self.listComponent?.reloadTableView()
}
}
// MARK: - SBUGroupChannelListViewModelDelegate
open func groupChannelListViewModel(_ viewModel: SBUGroupChannelListViewModel,
didChangeChannelList channels: [GroupChannel]?,
needsToReload: Bool) {
if let channelList = channels {
self.listComponent?.updateEmptyView(type: (channelList.count == 0) ? .noChannels : .none)
}
guard needsToReload else { return }
self.listComponent?.reloadTableView()
}
open func groupChannelListViewModel(_ viewModel: SBUGroupChannelListViewModel,
didUpdateChannel channel: GroupChannel) { }
open func groupChannelListViewModel(_ viewModel: SBUGroupChannelListViewModel,
didLeaveChannel channel: GroupChannel) { }
}