Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save n1kron/d61e82a60c9d5e0875b1d60660273343 to your computer and use it in GitHub Desktop.
Save n1kron/d61e82a60c9d5e0875b1d60660273343 to your computer and use it in GitHub Desktop.
import UIKit
import AsyncDisplayKit
final class NewChatViewController: ASViewController<ASDisplayNode>, ASTableDataSource, ASTableDelegate {
struct State {
var itemCount: Int
var fetchingMore: Bool
static let empty = State(itemCount: 0, fetchingMore: false)
}
enum Action {
case beginBatchFetch
case endBatchFetch(resultCount: Int)
}
var tableNode: ASTableNode {
return node as! ASTableNode
}
fileprivate var messages = [Message]()
fileprivate var offset = 0
fileprivate var stopLoadMessages = false
fileprivate(set) var state: State = .empty
init() {
super.init(node: ASTableNode())
tableNode.delegate = self
tableNode.dataSource = self
tableNode.view.allowsSelection = false
tableNode.view.separatorStyle = .none
tableNode.view.keyboardDismissMode = .interactive
tableNode.inverted = true
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
// MARK: ASTableNode data source and delegate.
func numberOfSections(in tableNode: ASTableNode) -> Int {
return 1
}
func tableNode(_ tableNode: ASTableNode, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
func tableNode(_ tableNode: ASTableNode, nodeForRowAt indexPath: IndexPath) -> ASCellNode {
let node = ASTextCellNode()
let currentMessage = messages[indexPath.row]
//if you need parse html use this:
//node.textNode.text = currentMessage.text?.html2AttributedString
node.text = currentMessage.text
return node
}
func tableNode(_ tableNode: ASTableNode, willBeginBatchFetchWith context: ASBatchContext) {
DispatchQueue.main.async {
let oldState = self.state
self.state = NewChatViewController.handleAction(.beginBatchFetch, fromState: oldState)
self.renderDiff(oldState)
}
self.fetchDataWithCompletion { resultCount in
if !self.stopLoadMessages {
let action = Action.endBatchFetch(resultCount: resultCount)
let oldState = self.state
self.state = NewChatViewController.handleAction(action, fromState: oldState)
self.renderDiff(oldState)
context.completeBatchFetching(true)
}
}
}
fileprivate func renderDiff(_ oldState: State) {
self.tableNode.performBatchUpdates({
let indexPaths = (oldState.itemCount ..< state.itemCount).map { index in
IndexPath(row: index, section: 0)
}
tableNode.insertRows(at: indexPaths, with: .none)
}, completion:nil)
}
fileprivate func fetchDataWithCompletion(_ completion: @escaping (Int) -> Void) {
ChatApi.fetchChat(offset: self.offset, limit: 100, completed: {[weak self] (messages,suggestions,placeholder) in
self?.stopLoadMessages = messages.isEmpty
messages.forEach({(message) in
self?.messages.append(message)
})
self?.offset += 100
completion(messages.count)
}, error: {
})
}
fileprivate static func handleAction(_ action: Action, fromState state: State) -> State {
var state = state
switch action {
case .beginBatchFetch:
state.fetchingMore = true
case let .endBatchFetch(resultCount):
state.itemCount += resultCount
state.fetchingMore = false
}
return state
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment