diff --git a/Yep/Extensions/UITableView+Yep.swift b/Yep/Extensions/UITableView+Yep.swift index 44b2f1f8..a1821bf5 100644 --- a/Yep/Extensions/UITableView+Yep.swift +++ b/Yep/Extensions/UITableView+Yep.swift @@ -14,6 +14,7 @@ extension UITableView { case None case ReloadData + case ReloadIndexPaths([NSIndexPath]) case Insert([NSIndexPath]) var needsLabor: Bool { @@ -23,6 +24,8 @@ extension UITableView { return false case .ReloadData: return true + case .ReloadIndexPaths: + return true case .Insert: return true } @@ -31,12 +34,19 @@ extension UITableView { func performWithTableView(tableView: UITableView) { switch self { + case .None: println("tableView WayToUpdate: None") break + case .ReloadData: println("tableView WayToUpdate: ReloadData") tableView.reloadData() + + case .ReloadIndexPaths(let indexPaths): + println("tableView WayToUpdate: ReloadIndexPaths") + tableView.reloadRowsAtIndexPaths(indexPaths, withRowAnimation: .None) + case .Insert(let indexPaths): println("tableView WayToUpdate: Insert") tableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: .None) diff --git a/Yep/Images.xcassets/feed_container_background.imageset/Contents.json b/Yep/Images.xcassets/feed_container_background.imageset/Contents.json new file mode 100644 index 00000000..c0abd5b3 --- /dev/null +++ b/Yep/Images.xcassets/feed_container_background.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "feed_container_background.pdf", + "resizing" : { + "mode" : "9-part", + "center" : { + "mode" : "tile", + "width" : 1, + "height" : 1 + }, + "cap-insets" : { + "bottom" : 5, + "top" : 5, + "right" : 5, + "left" : 5 + } + } + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Yep/Images.xcassets/feed_container_background.imageset/feed_container_background.pdf b/Yep/Images.xcassets/feed_container_background.imageset/feed_container_background.pdf new file mode 100644 index 00000000..8052f688 Binary files /dev/null and b/Yep/Images.xcassets/feed_container_background.imageset/feed_container_background.pdf differ diff --git a/Yep/Realm/Models.swift b/Yep/Realm/Models.swift index aff0e74f..fe8cdb6a 100644 --- a/Yep/Realm/Models.swift +++ b/Yep/Realm/Models.swift @@ -513,7 +513,7 @@ class Message: Object { dynamic var textContent: String = "" var textContentToShow: String { if deletedByCreator { - return NSLocalizedString("Deleted by creator.", comment: "") + return NSLocalizedString("Recalled by creator.", comment: "") } else { return textContent } diff --git a/Yep/ViewControllers/Conversation/ConversationViewController.swift b/Yep/ViewControllers/Conversation/ConversationViewController.swift index 4fe9202a..3a4b8bdd 100644 --- a/Yep/ViewControllers/Conversation/ConversationViewController.swift +++ b/Yep/ViewControllers/Conversation/ConversationViewController.swift @@ -289,13 +289,13 @@ enum ConversationFeed { class ConversationViewController: BaseViewController { - var conversationFeed: ConversationFeed? - var conversation: Conversation! + var conversationFeed: ConversationFeed? var afterSentMessageAction: (() -> Void)? - var afterDeletedFeedAction: (() -> Void)? + var conversationDirtyAction: (() -> Void)? + var conversationIsDirty = false private var selectedIndexPathForMenu: NSIndexPath? @@ -1343,6 +1343,10 @@ class ConversationViewController: BaseViewController { override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) + if conversationIsDirty { + conversationDirtyAction?() + } + if let checkTypingStatusTimer = checkTypingStatusTimer { checkTypingStatusTimer.invalidate() } @@ -2552,6 +2556,8 @@ class ConversationViewController: BaseViewController { if messageIDs == nil { afterSentMessageAction?() + conversationIsDirty = true + if isSubscribeViewShowing { realm.beginWrite() diff --git a/Yep/ViewControllers/Feeds/FeedsViewController.swift b/Yep/ViewControllers/Feeds/FeedsViewController.swift index 4fb5c8e9..de9831e4 100644 --- a/Yep/ViewControllers/Feeds/FeedsViewController.swift +++ b/Yep/ViewControllers/Feeds/FeedsViewController.swift @@ -431,7 +431,12 @@ class FeedsViewController: BaseViewController { private var currentPageIndex = 1 private var isFetchingFeeds = false - private func updateFeeds(isLoadMore isLoadMore: Bool = false, finish: (() -> Void)? = nil) { + enum UpdateFeedsMode { + case Top + case LoadMore + case Static + } + private func updateFeeds(mode mode: UpdateFeedsMode = .Top, finish: (() -> Void)? = nil) { if isFetchingFeeds { finish?() @@ -440,15 +445,17 @@ class FeedsViewController: BaseViewController { isFetchingFeeds = true - if !isLoadMore && feeds.isEmpty { + if mode == .Top && feeds.isEmpty { activityIndicator.startAnimating() } - if isLoadMore { - currentPageIndex++ - - } else { + switch mode { + case .Top: currentPageIndex = 1 + case .LoadMore: + currentPageIndex++ + case .Static: + break } let failureHandler: (Reason, String?) -> Void = { reason, errorMessage in @@ -489,7 +496,11 @@ class FeedsViewController: BaseViewController { wayToUpdate = .ReloadData } - if isLoadMore { + switch mode { + case .Top: + strongSelf.feeds = newFeeds + + case .LoadMore: let oldFeedsCount = strongSelf.feeds.count strongSelf.feeds += newFeeds let newFeedsCount = strongSelf.feeds.count @@ -499,12 +510,26 @@ class FeedsViewController: BaseViewController { wayToUpdate = .Insert(indexPaths) } - } else { - strongSelf.feeds = newFeeds + case .Static: + var indexesOfMessagesCountUpdated = [Int]() + newFeeds.forEach({ feed in + if let index = strongSelf.feeds.indexOf(feed) { + if strongSelf.feeds[index].messagesCount != feed.messagesCount { + strongSelf.feeds[index].messagesCount = feed.messagesCount + indexesOfMessagesCountUpdated.append(index) + } + } + }) + + let indexPaths = indexesOfMessagesCountUpdated.map({ NSIndexPath(forRow: $0, inSection: Section.Feed.rawValue) }) + + wayToUpdate = .ReloadIndexPaths(indexPaths) } if !wayToUpdate.needsLabor && !newFeeds.isEmpty { + var indexesOfMessagesCountUpdated = [Int]() + if newFeeds.count == oldFeeds.count { var index = 0 @@ -515,6 +540,8 @@ class FeedsViewController: BaseViewController { if newFeed.id != oldFeed.id { wayToUpdate = .ReloadData break + } else if newFeed.messagesCount != oldFeed.messagesCount { + indexesOfMessagesCountUpdated.append(index) } index += 1 @@ -523,6 +550,12 @@ class FeedsViewController: BaseViewController { } else { wayToUpdate = .ReloadData } + + if !wayToUpdate.needsLabor { + let indexPaths = indexesOfMessagesCountUpdated.map({ NSIndexPath(forRow: $0, inSection: Section.Feed.rawValue) }) + + wayToUpdate = .ReloadIndexPaths(indexPaths) + } } wayToUpdate.performWithTableView(strongSelf.feedsTableView) @@ -542,7 +575,7 @@ class FeedsViewController: BaseViewController { feedSortStyle = .Time } - let maxFeedID = (isLoadMore && (feedSortStyle == FeedSortStyle.Time)) ? feeds.last?.id : nil + let maxFeedID = (mode == .LoadMore && (feedSortStyle == FeedSortStyle.Time)) ? feeds.last?.id : nil discoverFeedsWithSortStyle(feedSortStyle, skill: skill, pageIndex: currentPageIndex, perPage: perPage, maxFeedID: maxFeedID, failureHandler:failureHandler, completion: completion) } @@ -676,10 +709,15 @@ class FeedsViewController: BaseViewController { vc.conversation = feedConversation vc.conversationFeed = ConversationFeed.DiscoveredFeedType(feed) + vc.afterDeletedFeedAction = { [weak self] in self?.updateFeeds() } + vc.conversationDirtyAction = { [weak self] in + self?.updateFeeds(mode: .Static) + } + case "presentNewFeed": guard let @@ -1150,7 +1188,7 @@ extension FeedsViewController: UITableViewDataSource, UITableViewDelegate { cell.loadingActivityIndicator.startAnimating() } - updateFeeds(isLoadMore: true, finish: { [weak cell] in + updateFeeds(mode: .LoadMore, finish: { [weak cell] in cell?.loadingActivityIndicator.stopAnimating() }) diff --git a/Yep/Views/ContainerViews/FeedGithubRepoContainerView.swift b/Yep/Views/ContainerViews/FeedGithubRepoContainerView.swift index 8e0e68f8..f77a8fe0 100644 --- a/Yep/Views/ContainerViews/FeedGithubRepoContainerView.swift +++ b/Yep/Views/ContainerViews/FeedGithubRepoContainerView.swift @@ -12,6 +12,12 @@ class FeedGithubRepoContainerView: UIView { var tapAction: (() -> Void)? + lazy var backgroundImageView: UIImageView = { + let imageView = UIImageView() + imageView.image = UIImage(named: "feed_container_background") + return imageView + }() + lazy var iconImageView: UIImageView = { let imageView = UIImageView() imageView.image = UIImage(named: "icon_repo") @@ -51,23 +57,34 @@ class FeedGithubRepoContainerView: UIView { private func makeUI() { + backgroundColor = UIColor.whiteColor() + tintAdjustmentMode = .Normal + + addSubview(backgroundImageView) addSubview(iconImageView) addSubview(nameLabel) addSubview(descriptionLabel) addSubview(accessoryImageView) + backgroundImageView.translatesAutoresizingMaskIntoConstraints = false iconImageView.translatesAutoresizingMaskIntoConstraints = false nameLabel.translatesAutoresizingMaskIntoConstraints = false descriptionLabel.translatesAutoresizingMaskIntoConstraints = false accessoryImageView.translatesAutoresizingMaskIntoConstraints = false let views = [ + "backgroundImageView": backgroundImageView, "iconImageView": iconImageView, "nameLabel": nameLabel, "descriptionLabel": descriptionLabel, "accessoryImageView": accessoryImageView, ] + let backgroundH = NSLayoutConstraint.constraintsWithVisualFormat("H:|[backgroundImageView]|", options: [], metrics: nil, views: views) + let backgroundV = NSLayoutConstraint.constraintsWithVisualFormat("V:|[backgroundImageView]|", options: [], metrics: nil, views: views) + NSLayoutConstraint.activateConstraints(backgroundH) + NSLayoutConstraint.activateConstraints(backgroundV) + let constraintsH = NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[iconImageView(16)]-10-[nameLabel]-5-[accessoryImageView(8)]-10-|", options: [], metrics: nil, views: views) iconImageView.setContentHuggingPriority(UILayoutPriorityDefaultHigh, forAxis: .Horizontal) diff --git a/Yep/Views/ContainerViews/FeedLocationContainerView.swift b/Yep/Views/ContainerViews/FeedLocationContainerView.swift index 41a7987c..ef7d8656 100644 --- a/Yep/Views/ContainerViews/FeedLocationContainerView.swift +++ b/Yep/Views/ContainerViews/FeedLocationContainerView.swift @@ -12,6 +12,12 @@ class FeedLocationContainerView: UIView { var tapAction: (() -> Void)? + lazy var backgroundImageView: UIImageView = { + let imageView = UIImageView() + imageView.image = UIImage(named: "feed_container_background") + return imageView + }() + lazy var mapImageView: UIImageView = { let imageView = UIImageView() imageView.contentMode = .ScaleAspectFill @@ -49,22 +55,30 @@ class FeedLocationContainerView: UIView { private func makeUI() { + addSubview(backgroundImageView) addSubview(mapImageView) addSubview(pinImageView) addSubview(horizontalLineView) addSubview(nameLabel) + backgroundImageView.translatesAutoresizingMaskIntoConstraints = false mapImageView.translatesAutoresizingMaskIntoConstraints = false pinImageView.translatesAutoresizingMaskIntoConstraints = false horizontalLineView.translatesAutoresizingMaskIntoConstraints = false nameLabel.translatesAutoresizingMaskIntoConstraints = false let views = [ + "backgroundImageView": backgroundImageView, "mapImageView": mapImageView, "horizontalLineView": horizontalLineView, "nameLabel": nameLabel, ] + let backgroundH = NSLayoutConstraint.constraintsWithVisualFormat("H:|[backgroundImageView]|", options: [], metrics: nil, views: views) + let backgroundV = NSLayoutConstraint.constraintsWithVisualFormat("V:|[backgroundImageView]|", options: [], metrics: nil, views: views) + NSLayoutConstraint.activateConstraints(backgroundH) + NSLayoutConstraint.activateConstraints(backgroundV) + let constraintsH1 = NSLayoutConstraint.constraintsWithVisualFormat("H:|[mapImageView]|", options: [], metrics: nil, views: views) let constraintsH2 = NSLayoutConstraint.constraintsWithVisualFormat("H:|[horizontalLineView]|", options: [], metrics: nil, views: views) let constraintsH3 = NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[nameLabel]-10-|", options: [], metrics: nil, views: views) diff --git a/Yep/Views/ContainerViews/FeedMediaContainerView.swift b/Yep/Views/ContainerViews/FeedMediaContainerView.swift index 24cce38e..e67fe291 100644 --- a/Yep/Views/ContainerViews/FeedMediaContainerView.swift +++ b/Yep/Views/ContainerViews/FeedMediaContainerView.swift @@ -13,6 +13,12 @@ class FeedMediaContainerView: UIView { var tapMediaAction: ((mediaImageView: UIImageView) -> Void)? + lazy var backgroundImageView: UIImageView = { + let imageView = UIImageView() + imageView.image = UIImage(named: "feed_container_background") + return imageView + }() + lazy var mediaImageView: UIImageView = { let imageView = UIImageView() imageView.contentMode = .ScaleAspectFill @@ -44,20 +50,28 @@ class FeedMediaContainerView: UIView { private func makeUI() { + addSubview(backgroundImageView) addSubview(mediaImageView) addSubview(horizontalLineView) addSubview(linkContainerView) + backgroundImageView.translatesAutoresizingMaskIntoConstraints = false mediaImageView.translatesAutoresizingMaskIntoConstraints = false horizontalLineView.translatesAutoresizingMaskIntoConstraints = false linkContainerView.translatesAutoresizingMaskIntoConstraints = false let views = [ + "backgroundImageView": backgroundImageView, "mediaImageView": mediaImageView, "horizontalLineView": horizontalLineView, "linkContainerView": linkContainerView, ] + let backgroundH = NSLayoutConstraint.constraintsWithVisualFormat("H:|[backgroundImageView]|", options: [], metrics: nil, views: views) + let backgroundV = NSLayoutConstraint.constraintsWithVisualFormat("V:|[backgroundImageView]|", options: [], metrics: nil, views: views) + NSLayoutConstraint.activateConstraints(backgroundH) + NSLayoutConstraint.activateConstraints(backgroundV) + let constraintsH = NSLayoutConstraint.constraintsWithVisualFormat("H:|[mediaImageView]|", options: [], metrics: nil, views: views) let linkContainerViewHeight: CGFloat = Ruler.iPhoneHorizontal(44, 50, 50).value diff --git a/Yep/zh-Hans.lproj/Localizable.strings b/Yep/zh-Hans.lproj/Localizable.strings index 8595eff8..e1fc8f76 100644 --- a/Yep/zh-Hans.lproj/Localizable.strings +++ b/Yep/zh-Hans.lproj/Localizable.strings @@ -726,5 +726,5 @@ "Hide" = "隐藏"; -"Deleted by creator." = "被创建者删除。"; +"Recalled by creator." = "消息已被撤回。";