mirror of
https://github.com/wahyd4/Yep.git
synced 2026-08-19 01:36:18 +10:00
772 lines
26 KiB
Swift
772 lines
26 KiB
Swift
//
|
|
// FeedsViewController.swift
|
|
// Yep
|
|
//
|
|
// Created by nixzhu on 15/9/25.
|
|
// Copyright © 2015年 Catch Inc. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
import RealmSwift
|
|
|
|
class FeedsViewController: BaseViewController {
|
|
|
|
var skill: Skill?
|
|
|
|
@IBOutlet weak var feedsTableView: UITableView!
|
|
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
|
|
|
|
var filterBarItem: UIBarButtonItem?
|
|
|
|
lazy var filterView: DiscoverFilterView = DiscoverFilterView()
|
|
|
|
lazy var skillTitleView: UIView = {
|
|
|
|
let titleLabel = UILabel()
|
|
|
|
let textAttributes = [
|
|
NSForegroundColorAttributeName: UIColor.whiteColor(),
|
|
NSFontAttributeName: UIFont.skillHomeTextLargeFont()
|
|
]
|
|
|
|
let titleAttr = NSMutableAttributedString(string: self.skill?.localName ?? "", attributes:textAttributes)
|
|
|
|
titleLabel.attributedText = titleAttr
|
|
titleLabel.textAlignment = NSTextAlignment.Center
|
|
titleLabel.backgroundColor = UIColor.yepTintColor()
|
|
titleLabel.sizeToFit()
|
|
|
|
titleLabel.bounds = CGRectInset(titleLabel.frame, -25.0, -4.0)
|
|
|
|
titleLabel.layer.cornerRadius = titleLabel.frame.size.height/2.0
|
|
titleLabel.layer.masksToBounds = true
|
|
|
|
return titleLabel
|
|
}()
|
|
|
|
lazy var pullToRefreshView: PullToRefreshView = {
|
|
|
|
let pullToRefreshView = PullToRefreshView()
|
|
pullToRefreshView.delegate = self
|
|
|
|
self.feedsTableView.insertSubview(pullToRefreshView, atIndex: 0)
|
|
|
|
pullToRefreshView.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
let viewsDictionary = [
|
|
"pullToRefreshView": pullToRefreshView,
|
|
"view": self.view,
|
|
]
|
|
|
|
let constraintsV = NSLayoutConstraint.constraintsWithVisualFormat("V:|-(-200)-[pullToRefreshView(200)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewsDictionary)
|
|
|
|
// 非常奇怪,若直接用 "H:|[pullToRefreshView]|" 得到的实际宽度为 0
|
|
let constraintsH = NSLayoutConstraint.constraintsWithVisualFormat("H:|[pullToRefreshView(==view)]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewsDictionary)
|
|
|
|
NSLayoutConstraint.activateConstraints(constraintsV)
|
|
NSLayoutConstraint.activateConstraints(constraintsH)
|
|
|
|
return pullToRefreshView
|
|
}()
|
|
|
|
let feedSkillUsersCellID = "FeedSkillUsersCell"
|
|
let feedCellID = "FeedCell"
|
|
let loadMoreTableViewCellID = "LoadMoreTableViewCell"
|
|
|
|
lazy var noFeedsFooterView: InfoView = InfoView(NSLocalizedString("No Feeds.", comment: ""))
|
|
|
|
var feeds = [DiscoveredFeed]()
|
|
|
|
private func updateFeedsTableViewOrInsertWithIndexPaths(indexPaths: [NSIndexPath]?) {
|
|
|
|
dispatch_async(dispatch_get_main_queue()) { [weak self] in
|
|
|
|
if let indexPaths = indexPaths {
|
|
|
|
// refresh skillUsers
|
|
|
|
let skillUsersIndexPath = NSIndexPath(forRow: 0, inSection: Section.SkillUsers.rawValue)
|
|
if let cell = self?.feedsTableView.cellForRowAtIndexPath(skillUsersIndexPath) as? FeedSkillUsersCell, feeds = self?.feeds {
|
|
cell.configureWithFeeds(feeds)
|
|
}
|
|
|
|
// insert
|
|
|
|
self?.feedsTableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: .Automatic)
|
|
|
|
} else {
|
|
|
|
// or reload
|
|
|
|
self?.feedsTableView.reloadData()
|
|
}
|
|
|
|
if let strongSelf = self {
|
|
strongSelf.feedsTableView.tableFooterView = strongSelf.feeds.isEmpty ? strongSelf.noFeedsFooterView : UIView()
|
|
}
|
|
}
|
|
}
|
|
|
|
private var feedHeightHash = [String: CGFloat]()
|
|
|
|
private func heightOfFeed(feed: DiscoveredFeed) -> CGFloat {
|
|
|
|
let key = feed.id
|
|
|
|
if let height = feedHeightHash[key] {
|
|
return height
|
|
} else {
|
|
let height = FeedCell.heightOfFeed(feed)
|
|
|
|
if !key.isEmpty {
|
|
feedHeightHash[key] = height
|
|
}
|
|
|
|
return height
|
|
}
|
|
}
|
|
|
|
var feedSortStyle: FeedSortStyle = .Match {
|
|
didSet {
|
|
feeds = []
|
|
feedsTableView.reloadData()
|
|
|
|
filterBarItem?.title = feedSortStyle.nameWithArrow
|
|
|
|
updateFeeds()
|
|
|
|
YepUserDefaults.feedSortStyle.value = feedSortStyle.rawValue
|
|
}
|
|
}
|
|
|
|
var navigationControllerDelegate: ConversationMessagePreviewNavigationControllerDelegate?
|
|
var originalNavigationControllerDelegate: UINavigationControllerDelegate?
|
|
|
|
deinit {
|
|
print("Deinit FeedsViewControler")
|
|
}
|
|
|
|
override func viewDidAppear(animated: Bool) {
|
|
super.viewDidAppear(animated)
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
|
|
// 优先处理侧滑,而不是 scrollView 的上下滚动,避免出现你想侧滑返回的时候,结果触发了 scrollView 的上下滚动
|
|
if let gestures = navigationController?.view.gestureRecognizers {
|
|
for recognizer in gestures {
|
|
if recognizer.isKindOfClass(UIScreenEdgePanGestureRecognizer) {
|
|
feedsTableView.panGestureRecognizer.requireGestureRecognizerToFail(recognizer as! UIScreenEdgePanGestureRecognizer)
|
|
println("Require UIScreenEdgePanGestureRecognizer to failed")
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
title = NSLocalizedString("Feeds", comment: "")
|
|
|
|
if skill != nil {
|
|
navigationItem.titleView = skillTitleView
|
|
// Add to Me
|
|
|
|
if let skillID = skill?.id {
|
|
if let
|
|
myUserID = YepUserDefaults.userID.value,
|
|
realm = try? Realm(),
|
|
me = userWithUserID(myUserID, inRealm: realm) {
|
|
|
|
let predicate = NSPredicate(format: "skillID = %@", skillID)
|
|
|
|
if me.masterSkills.filter(predicate).count == 0
|
|
&& me.learningSkills.filter(predicate).count == 0 {
|
|
let addSkillToMeButton = UIBarButtonItem(title: NSLocalizedString("Add to Me", comment: ""), style: .Plain, target: self, action: "addSkillToMe")
|
|
navigationItem.rightBarButtonItem = addSkillToMeButton
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
filterBarItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.Plain, target: self, action: "showFilter:")
|
|
navigationItem.leftBarButtonItem = filterBarItem
|
|
}
|
|
|
|
feedsTableView.backgroundColor = UIColor.whiteColor()
|
|
feedsTableView.tableFooterView = UIView()
|
|
feedsTableView.separatorColor = UIColor.yepCellSeparatorColor()
|
|
|
|
feedsTableView.registerNib(UINib(nibName: feedSkillUsersCellID, bundle: nil), forCellReuseIdentifier: feedSkillUsersCellID)
|
|
feedsTableView.registerNib(UINib(nibName: feedCellID, bundle: nil), forCellReuseIdentifier: feedCellID)
|
|
feedsTableView.registerNib(UINib(nibName: loadMoreTableViewCellID, bundle: nil), forCellReuseIdentifier: loadMoreTableViewCellID)
|
|
|
|
if let
|
|
value = YepUserDefaults.feedSortStyle.value,
|
|
_feedSortStyle = FeedSortStyle(rawValue: value) {
|
|
|
|
feedSortStyle = _feedSortStyle
|
|
|
|
} else {
|
|
feedSortStyle = .Match
|
|
}
|
|
}
|
|
|
|
// MARK: Actions
|
|
|
|
func addSkillToMe() {
|
|
println("addSkillToMe")
|
|
|
|
if let skillID = skill?.id, skillLocalName = skill?.localName {
|
|
|
|
let doAddSkillToSkillSet: SkillSet -> Void = { skillSet in
|
|
|
|
addSkillWithSkillID(skillID, toSkillSet: skillSet, failureHandler: { reason, errorMessage in
|
|
defaultFailureHandler(reason, errorMessage: errorMessage)
|
|
|
|
}, completion: { [weak self] _ in
|
|
|
|
YepAlert.alert(title: NSLocalizedString("Success", comment: ""), message: String(format: NSLocalizedString("Added %@ to %@ successfully!", comment: ""), skillLocalName, skillSet.name), dismissTitle: NSLocalizedString("OK", comment: ""), inViewController: self, withDismissAction: nil)
|
|
|
|
dispatch_async(dispatch_get_main_queue()) {
|
|
self?.navigationItem.rightBarButtonItem = nil
|
|
}
|
|
|
|
syncMyInfoAndDoFurtherAction {
|
|
}
|
|
})
|
|
}
|
|
|
|
let alertController = UIAlertController(title: NSLocalizedString("Choose skill set", comment: ""), message: String(format: NSLocalizedString("Which skill set do you want %@ to be?", comment: ""), skillLocalName), preferredStyle: .Alert)
|
|
|
|
let cancelAction: UIAlertAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel) { action in
|
|
}
|
|
alertController.addAction(cancelAction)
|
|
|
|
let learningAction: UIAlertAction = UIAlertAction(title: SkillSet.Learning.name, style: .Default) { action in
|
|
doAddSkillToSkillSet(.Learning)
|
|
}
|
|
alertController.addAction(learningAction)
|
|
|
|
let masterAction: UIAlertAction = UIAlertAction(title: SkillSet.Master.name, style: .Default) { action in
|
|
doAddSkillToSkillSet(.Master)
|
|
}
|
|
alertController.addAction(masterAction)
|
|
|
|
presentViewController(alertController, animated: true, completion: nil)
|
|
}
|
|
}
|
|
|
|
override func viewWillAppear(animated: Bool) {
|
|
super.viewWillAppear(animated)
|
|
|
|
// 尝试恢复原始的 NavigationControllerDelegate,如果自定义 push 了才需要
|
|
if let delegate = originalNavigationControllerDelegate {
|
|
navigationController?.delegate = delegate
|
|
navigationControllerDelegate = nil
|
|
}
|
|
|
|
navigationController?.setNavigationBarHidden(false, animated: false)
|
|
|
|
tabBarController?.tabBar.hidden = (skill == nil) ? false : true
|
|
}
|
|
|
|
// MARK: - Actions
|
|
|
|
@IBAction func showFilter(sender: AnyObject) {
|
|
|
|
if feedSortStyle != .Time {
|
|
filterView.currentDiscoveredUserSortStyle = DiscoveredUserSortStyle(rawValue: feedSortStyle.rawValue)!
|
|
} else {
|
|
filterView.currentDiscoveredUserSortStyle = .LastSignIn
|
|
}
|
|
|
|
filterView.filterAction = { [weak self] discoveredUserSortStyle in
|
|
|
|
if discoveredUserSortStyle != .LastSignIn {
|
|
self?.feedSortStyle = FeedSortStyle(rawValue: discoveredUserSortStyle.rawValue)!
|
|
} else {
|
|
self?.feedSortStyle = .Time
|
|
}
|
|
}
|
|
|
|
if let window = view.window {
|
|
filterView.showInView(window)
|
|
}
|
|
}
|
|
|
|
var currentPageIndex = 1
|
|
var isFetchingFeeds = false
|
|
func updateFeeds(isLoadMore isLoadMore: Bool = false, finish: (() -> Void)? = nil) {
|
|
|
|
if isFetchingFeeds {
|
|
return
|
|
}
|
|
|
|
isFetchingFeeds = true
|
|
|
|
if !isLoadMore {
|
|
activityIndicator.startAnimating()
|
|
}
|
|
|
|
if isLoadMore {
|
|
currentPageIndex++
|
|
|
|
} else {
|
|
currentPageIndex = 1
|
|
}
|
|
|
|
let maxFeedID = (isLoadMore && (feedSortStyle == FeedSortStyle.Time)) ? feeds.last?.id : nil
|
|
|
|
discoverFeedsWithSortStyle(feedSortStyle, skill: skill, pageIndex: currentPageIndex, perPage: 25, maxFeedID: maxFeedID, failureHandler: { reason, errorMessage in
|
|
|
|
dispatch_async(dispatch_get_main_queue()) { [weak self] in
|
|
|
|
self?.isFetchingFeeds = false
|
|
|
|
self?.activityIndicator.stopAnimating()
|
|
|
|
finish?()
|
|
}
|
|
|
|
defaultFailureHandler(reason, errorMessage: errorMessage)
|
|
|
|
}, completion: { [weak self] feeds in
|
|
|
|
dispatch_async(dispatch_get_main_queue()) { [weak self] in
|
|
|
|
self?.isFetchingFeeds = false
|
|
|
|
self?.activityIndicator.stopAnimating()
|
|
|
|
finish?()
|
|
}
|
|
|
|
if let strongSelf = self {
|
|
|
|
// let oldFeedSet = Set(strongSelf.feeds)
|
|
// let newFeedSet = Set(feeds)
|
|
|
|
// let unionFeedSet = oldFeedSet.union(newFeedSet)
|
|
// let allNewFeedSet = newFeedSet.subtract(oldFeedSet)
|
|
|
|
// let allFeeds = Array(unionFeedSet)
|
|
//
|
|
// let newIndexPaths = allNewFeedSet.map({ allFeeds.indexOf($0) }).flatMap({ $0 }).map({ NSIndexPath(forRow: $0, inSection: Section.Feed.rawValue) })
|
|
|
|
dispatch_async(dispatch_get_main_queue()) {
|
|
|
|
if isLoadMore {
|
|
strongSelf.feeds += feeds
|
|
|
|
} else {
|
|
strongSelf.feeds = feeds
|
|
}
|
|
|
|
// 确保有新的才 reload
|
|
if !feeds.isEmpty {
|
|
strongSelf.feedsTableView.reloadData() // 服务端有新的排序算法,以及避免刷新后消息数字更新不及时的问题
|
|
}
|
|
|
|
// if newIndexPaths.count == allNewFeedSet.count {
|
|
// strongSelf.updateFeedsTableViewOrInsertWithIndexPaths(newIndexPaths)
|
|
//
|
|
// } else {
|
|
// strongSelf.updateFeedsTableViewOrInsertWithIndexPaths(nil)
|
|
// }
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
@IBAction func showNewFeed(sender: AnyObject) {
|
|
|
|
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("NewFeedViewController") as! NewFeedViewController
|
|
|
|
vc.preparedSkill = skill
|
|
|
|
vc.afterCreatedFeedAction = { [weak self] feed in
|
|
|
|
dispatch_async(dispatch_get_main_queue()) {
|
|
|
|
if let strongSelf = self {
|
|
|
|
strongSelf.feeds.insert(feed, atIndex: 0)
|
|
|
|
let indexPath = NSIndexPath(forRow: 0, inSection: Section.Feed.rawValue)
|
|
strongSelf.updateFeedsTableViewOrInsertWithIndexPaths([indexPath])
|
|
}
|
|
}
|
|
|
|
joinGroup(groupID: feed.groupID, failureHandler: nil, completion: {
|
|
|
|
})
|
|
}
|
|
|
|
let navi = UINavigationController(rootViewController: vc)
|
|
|
|
self.presentViewController(navi, animated: true, completion: nil)
|
|
}
|
|
|
|
// MARK: - Navigation
|
|
|
|
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
|
|
|
|
guard let identifier = segue.identifier else {
|
|
return
|
|
}
|
|
|
|
switch identifier {
|
|
|
|
case "showProfile":
|
|
|
|
let vc = segue.destinationViewController as! ProfileViewController
|
|
|
|
if let indexPath = sender as? NSIndexPath {
|
|
let discoveredUser = feeds[indexPath.row].creator
|
|
vc.profileUser = ProfileUser.DiscoveredUserType(discoveredUser)
|
|
}
|
|
|
|
vc.fromType = .None
|
|
vc.setBackButtonWithTitle()
|
|
|
|
vc.hidesBottomBarWhenPushed = true
|
|
|
|
case "showSkillHome":
|
|
|
|
let vc = segue.destinationViewController as! SkillHomeViewController
|
|
|
|
if let skill = skill {
|
|
vc.skill = SkillCell.Skill(ID: skill.id, localName: skill.localName, coverURLString: skill.coverURLString, category: nil)
|
|
}
|
|
|
|
vc.hidesBottomBarWhenPushed = true
|
|
|
|
case "showFeedsWithSkill":
|
|
|
|
let vc = segue.destinationViewController as! FeedsViewController
|
|
|
|
if let indexPath = sender as? NSIndexPath {
|
|
vc.skill = feeds[indexPath.row].skill
|
|
}
|
|
|
|
vc.hidesBottomBarWhenPushed = true
|
|
|
|
case "showConversation":
|
|
|
|
let vc = segue.destinationViewController as! ConversationViewController
|
|
|
|
guard let
|
|
indexPath = sender as? NSIndexPath,
|
|
feed = feeds[safe: indexPath.row],
|
|
realm = try? Realm(),
|
|
feedConversation = vc.prepareConversationForFeed(feed, inRealm: realm) else {
|
|
return
|
|
}
|
|
|
|
vc.conversation = feedConversation
|
|
vc.conversationFeed = ConversationFeed.DiscoveredFeedType(feed)
|
|
vc.afterDeletedConversationAction = { [weak self] in
|
|
self?.updateFeeds()
|
|
}
|
|
|
|
case "showFeedMedia":
|
|
|
|
let info = sender as! [String: AnyObject]
|
|
|
|
let vc = segue.destinationViewController as! MessageMediaViewController
|
|
|
|
if let box = info["attachments"] as? Box<[DiscoveredAttachment]> {
|
|
let attachments = box.value
|
|
vc.previewMedias = attachments.map({ PreviewMedia.AttachmentType(attachment: $0) })
|
|
}
|
|
|
|
if let index = info["index"] as? Int {
|
|
vc.startIndex = index
|
|
}
|
|
|
|
let transitionView = info["transitionView"] as! UIImageView
|
|
|
|
let delegate = ConversationMessagePreviewNavigationControllerDelegate()
|
|
delegate.isFeedMedia = true
|
|
delegate.snapshot = UIScreen.mainScreen().snapshotViewAfterScreenUpdates(false)
|
|
|
|
var frame = transitionView.convertRect(transitionView.frame, toView: view)
|
|
delegate.frame = frame
|
|
if let image = transitionView.image {
|
|
let width = image.size.width
|
|
let height = image.size.height
|
|
if width > height {
|
|
let newWidth = frame.width * (width / height)
|
|
frame.origin.x -= (newWidth - frame.width) / 2
|
|
frame.size.width = newWidth
|
|
} else {
|
|
let newHeight = frame.height * (height / width)
|
|
frame.origin.y -= (newHeight - frame.height) / 2
|
|
frame.size.height = newHeight
|
|
}
|
|
delegate.thumbnailImage = image
|
|
}
|
|
delegate.thumbnailFrame = frame
|
|
|
|
delegate.transitionView = transitionView
|
|
|
|
navigationControllerDelegate = delegate
|
|
|
|
// 在自定义 push 之前,记录原始的 NavigationControllerDelegate 以便 pop 后恢复
|
|
originalNavigationControllerDelegate = navigationController!.delegate
|
|
|
|
navigationController?.delegate = delegate
|
|
|
|
break
|
|
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - UITableViewDataSource, UITableViewDelegate
|
|
|
|
extension FeedsViewController: UITableViewDataSource, UITableViewDelegate {
|
|
|
|
enum Section: Int {
|
|
case SkillUsers
|
|
case Feed
|
|
case LoadMore
|
|
}
|
|
|
|
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
|
|
|
|
return 3
|
|
}
|
|
|
|
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
|
|
switch section {
|
|
case Section.SkillUsers.rawValue:
|
|
return (skill == nil) ? 0 : 1
|
|
case Section.Feed.rawValue:
|
|
return feeds.count
|
|
case Section.LoadMore.rawValue:
|
|
return feeds.isEmpty ? 0 : 1
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
|
|
|
|
switch indexPath.section {
|
|
|
|
case Section.SkillUsers.rawValue:
|
|
|
|
let cell = tableView.dequeueReusableCellWithIdentifier(feedSkillUsersCellID) as! FeedSkillUsersCell
|
|
|
|
cell.configureWithFeeds(feeds)
|
|
|
|
return cell
|
|
|
|
case Section.Feed.rawValue:
|
|
|
|
let cell = tableView.dequeueReusableCellWithIdentifier(feedCellID) as! FeedCell
|
|
|
|
let feed = feeds[indexPath.item]
|
|
|
|
cell.configureWithFeed(feed, needShowSkill: (skill == nil) ? true : false)
|
|
|
|
cell.tapAvatarAction = { [weak self] cell in
|
|
if let indexPath = tableView.indexPathForCell(cell) { // 不直接捕捉 indexPath
|
|
self?.performSegueWithIdentifier("showProfile", sender: indexPath)
|
|
}
|
|
}
|
|
|
|
cell.tapSkillAction = { [weak self] cell in
|
|
if let indexPath = tableView.indexPathForCell(cell) { // 不直接捕捉 indexPath
|
|
self?.performSegueWithIdentifier("showFeedsWithSkill", sender: indexPath)
|
|
}
|
|
}
|
|
|
|
cell.tapMediaAction = { [weak self] transitionView, image, attachments, index in
|
|
|
|
let vc = UIStoryboard(name: "MediaPreview", bundle: nil).instantiateViewControllerWithIdentifier("MediaPreviewViewController") as! MediaPreviewViewController
|
|
|
|
vc.previewMedias = attachments.map({ PreviewMedia.AttachmentType(attachment: $0) })
|
|
vc.startIndex = index
|
|
|
|
let transitionView = transitionView
|
|
let frame = transitionView.convertRect(transitionView.frame, toView: self?.view)
|
|
vc.previewImageViewInitalFrame = frame
|
|
vc.previewImage = image
|
|
|
|
transitionView.alpha = 0
|
|
vc.afterDismissAction = { [weak self] in
|
|
self?.view.window?.makeKeyAndVisible()
|
|
transitionView.alpha = 1
|
|
}
|
|
|
|
mediaPreviewWindow.rootViewController = vc
|
|
mediaPreviewWindow.windowLevel = UIWindowLevelAlert - 1
|
|
mediaPreviewWindow.makeKeyAndVisible()
|
|
|
|
/*
|
|
let info: [String: AnyObject] = [
|
|
"transitionView": transitionView,
|
|
"attachments": Box(value: attachments),
|
|
"index": index,
|
|
]
|
|
self?.performSegueWithIdentifier("showFeedMedia", sender: info)
|
|
*/
|
|
}
|
|
|
|
// simulate select effects when tap on messageTextView or cell.mediaCollectionView's space part
|
|
// 不能直接捕捉 indexPath,不然新插入后,之前捕捉的 indexPath 不能代表 cell 的新位置,模拟点击会错位到其它 cell
|
|
cell.touchesBeganAction = { [weak self] cell in
|
|
guard let indexPath = tableView.indexPathForCell(cell) else {
|
|
return
|
|
}
|
|
self?.tableView(tableView, willSelectRowAtIndexPath: indexPath)
|
|
tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: .None)
|
|
}
|
|
cell.touchesEndedAction = { [weak self] cell in
|
|
guard let indexPath = tableView.indexPathForCell(cell) else {
|
|
return
|
|
}
|
|
delay(0.03) { [weak self] in
|
|
self?.tableView(tableView, didSelectRowAtIndexPath: indexPath)
|
|
}
|
|
}
|
|
cell.touchesCancelledAction = { cell in
|
|
guard let indexPath = tableView.indexPathForCell(cell) else {
|
|
return
|
|
}
|
|
tableView.deselectRowAtIndexPath(indexPath, animated: true)
|
|
}
|
|
|
|
return cell
|
|
|
|
case Section.LoadMore.rawValue:
|
|
let cell = tableView.dequeueReusableCellWithIdentifier(loadMoreTableViewCellID) as! LoadMoreTableViewCell
|
|
return cell
|
|
|
|
default:
|
|
return UITableViewCell()
|
|
}
|
|
}
|
|
|
|
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
|
|
|
|
if indexPath.section == Section.LoadMore.rawValue {
|
|
|
|
if let cell = cell as? LoadMoreTableViewCell {
|
|
|
|
println("load more feeds")
|
|
|
|
if !cell.loadingActivityIndicator.isAnimating() {
|
|
cell.loadingActivityIndicator.startAnimating()
|
|
}
|
|
|
|
updateFeeds(isLoadMore: true, finish: { [weak cell] in
|
|
cell?.loadingActivityIndicator.stopAnimating()
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
|
|
|
|
switch indexPath.section {
|
|
|
|
case Section.SkillUsers.rawValue:
|
|
return 70
|
|
|
|
case Section.Feed.rawValue:
|
|
let feed = feeds[indexPath.item]
|
|
return heightOfFeed(feed)
|
|
|
|
case Section.LoadMore.rawValue:
|
|
return 60
|
|
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
|
|
return indexPath
|
|
}
|
|
|
|
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
|
|
|
|
tableView.deselectRowAtIndexPath(indexPath, animated: true)
|
|
|
|
switch indexPath.section {
|
|
|
|
case Section.SkillUsers.rawValue:
|
|
performSegueWithIdentifier("showSkillHome", sender: nil)
|
|
|
|
case Section.Feed.rawValue:
|
|
performSegueWithIdentifier("showConversation", sender: indexPath)
|
|
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
|
|
|
|
// Edit (for Delete)
|
|
|
|
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
|
|
|
|
return true
|
|
}
|
|
|
|
func tableView(tableView: UITableView, titleForDeleteConfirmationButtonForRowAtIndexPath indexPath: NSIndexPath) -> String? {
|
|
return NSLocalizedString("Report", comment: "")
|
|
}
|
|
|
|
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
|
|
|
|
if editingStyle == .Delete {
|
|
|
|
let feed = feeds[indexPath.item]
|
|
report(.Feed(feed))
|
|
|
|
tableView.setEditing(false, animated: true)
|
|
}
|
|
}
|
|
|
|
// MARK: UIScrollViewDelegate
|
|
|
|
func scrollViewDidScroll(scrollView: UIScrollView) {
|
|
|
|
pullToRefreshView.scrollViewDidScroll(scrollView)
|
|
}
|
|
|
|
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
|
|
|
|
pullToRefreshView.scrollViewWillEndDragging(scrollView, withVelocity: velocity, targetContentOffset: targetContentOffset)
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// MARK: PullToRefreshViewDelegate
|
|
|
|
extension FeedsViewController: PullToRefreshViewDelegate {
|
|
|
|
func pulllToRefreshViewDidRefresh(pulllToRefreshView: PullToRefreshView) {
|
|
|
|
activityIndicator.alpha = 0
|
|
|
|
updateFeeds { [weak self] in
|
|
pulllToRefreshView.endRefreshingAndDoFurtherAction() {}
|
|
|
|
self?.activityIndicator.alpha = 1
|
|
}
|
|
}
|
|
|
|
func scrollView() -> UIScrollView {
|
|
return feedsTableView
|
|
}
|
|
}
|
|
|