Merge branch 'develop' of https://github.com/CatchChat/Yep into develop

This commit is contained in:
kevinzhow
2016-01-06 19:41:05 +08:00
17 changed files with 583 additions and 99 deletions
+2 -2
View File
@@ -13,7 +13,7 @@ PODS:
- FXBlurView (1.6.4)
- JPush-iOS-SDK (1.8.8)
- KeyboardMan (0.5.2)
- Kingfisher (1.9.0)
- Kingfisher (1.9.1)
- MonkeyKing (0.0.2)
- MZFayeClient (1.0.1):
- Base64 (~> 1.0.1)
@@ -67,7 +67,7 @@ SPEC CHECKSUMS:
FXBlurView: db786c2561cb49a09ae98407f52460096ab8a44f
JPush-iOS-SDK: d4c097d8abbdd0837e24d44b41aacf64a6feddfd
KeyboardMan: b081c254c5c0adc794a49b4e97a86cb4ac917a66
Kingfisher: 163bafc1af6ae14d707e76ecba256d8db99dc955
Kingfisher: 98fedd5d44d982b331fc7303f9f6144b7d8ba289
MonkeyKing: 9be24307843a80f4cd3eca66adc12c67aefb83bb
MZFayeClient: 65e7ef67e61fbe7a7a8b196130541c9f06bcb5d8
Navi: 24f5c81aeb46b89d27168ec1d459581230ae2675
+4
View File
@@ -327,6 +327,7 @@
50F5AF961BBBCDA30033C9BC /* FeedMediaAddCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 50F5AF941BBBCDA30033C9BC /* FeedMediaAddCell.xib */; };
50F5AF991BBBD02A0033C9BC /* FeedMediaCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50F5AF971BBBD02A0033C9BC /* FeedMediaCell.swift */; };
50F5AF9A1BBBD02A0033C9BC /* FeedMediaCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 50F5AF981BBBD02A0033C9BC /* FeedMediaCell.xib */; };
50F6D32E1C3CBE0000CB673C /* FeedUploadingErrorContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50F6D32D1C3CBE0000CB673C /* FeedUploadingErrorContainerView.swift */; };
50FA9A441B661698009BF2A0 /* UIViewController+Yep.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50FA9A431B661698009BF2A0 /* UIViewController+Yep.swift */; };
50FD753D1C1FB4AC0050A382 /* FPSLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50FD753C1C1FB4AC0050A382 /* FPSLabel.swift */; };
50FD753F1C20FF8D0050A382 /* FeedMediaContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50FD753E1C20FF8D0050A382 /* FeedMediaContainerView.swift */; };
@@ -696,6 +697,7 @@
50F5AF941BBBCDA30033C9BC /* FeedMediaAddCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = FeedMediaAddCell.xib; path = Views/Cells/FeedMediaAdd/FeedMediaAddCell.xib; sourceTree = "<group>"; };
50F5AF971BBBD02A0033C9BC /* FeedMediaCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FeedMediaCell.swift; path = Views/Cells/FeedMedia/FeedMediaCell.swift; sourceTree = "<group>"; };
50F5AF981BBBD02A0033C9BC /* FeedMediaCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = FeedMediaCell.xib; path = Views/Cells/FeedMedia/FeedMediaCell.xib; sourceTree = "<group>"; };
50F6D32D1C3CBE0000CB673C /* FeedUploadingErrorContainerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FeedUploadingErrorContainerView.swift; path = Views/ContainerViews/FeedUploadingErrorContainerView.swift; sourceTree = "<group>"; };
50FA9A431B661698009BF2A0 /* UIViewController+Yep.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "UIViewController+Yep.swift"; path = "Extensions/UIViewController+Yep.swift"; sourceTree = "<group>"; };
50FD753C1C1FB4AC0050A382 /* FPSLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FPSLabel.swift; path = Views/Labels/FPSLabel.swift; sourceTree = "<group>"; };
50FD753E1C20FF8D0050A382 /* FeedMediaContainerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FeedMediaContainerView.swift; path = Views/ContainerViews/FeedMediaContainerView.swift; sourceTree = "<group>"; };
@@ -2206,6 +2208,7 @@
505082321C21130100643CEB /* FeedGithubRepoContainerView.swift */,
505082341C212E9200643CEB /* FeedLocationContainerView.swift */,
505082361C21377E00643CEB /* FeedVoiceContainerView.swift */,
50F6D32D1C3CBE0000CB673C /* FeedUploadingErrorContainerView.swift */,
);
name = ContainerViews;
sourceTree = "<group>";
@@ -2737,6 +2740,7 @@
6A56328E1BC90A4500397B53 /* DiscoverCardUserCell.swift in Sources */,
5016901C1BFB22180096C4F9 /* SocialWorkService.swift in Sources */,
0A0A11821AE389380008772C /* RegisterSkillsLayout.swift in Sources */,
50F6D32E1C3CBE0000CB673C /* FeedUploadingErrorContainerView.swift in Sources */,
50C0909B1ADE234F00CC6389 /* RegisterPickSkillsViewController.swift in Sources */,
5076FC5A1AF9DF6B00D7381A /* ConversationMessagePreviewTransitionManager.swift in Sources */,
50F5AF951BBBCDA30033C9BC /* FeedMediaAddCell.swift in Sources */,
+3
View File
@@ -266,6 +266,9 @@ class YepConfig {
struct Media {
static let imageWidth: CGFloat = 2048
static let imageHeight: CGFloat = 2048
static let miniImageWidth: CGFloat = 200
static let miniImageHeight: CGFloat = 200
}
struct Feedback {
+27 -3
View File
@@ -12,7 +12,7 @@ import CoreLocation
import Alamofire
#if STAGING
let yepBaseURL = NSURL(string: "https://park-staging.catchchatchina.com/api")!
let yepBaseURL = NSURL(string: "https://park-staging.catchchatchina.com")!
let fayeBaseURL = NSURL(string: "wss://faye-staging.catchchatchina.com/faye")!
#else
let yepBaseURL = NSURL(string: "https://api.soyep.com")!
@@ -1276,6 +1276,11 @@ struct DiscoveredUser: Hashable {
return false
}
static func fromUser(user: User) -> DiscoveredUser {
return DiscoveredUser(id: user.userID, username: user.username, nickname: user.nickname, introduction: user.introduction, avatarURLString: user.avatarURLString, badge: user.badge, createdUnixTime: user.createdUnixTime, lastSignInUnixTime: user.lastSignInUnixTime, longitude: user.longitude, latitude: user.latitude, distance: 0, masterSkills: [], learningSkills: [], socialAccountProviders: [], recently_updated_provider: nil)
}
}
func ==(lhs: DiscoveredUser, rhs: DiscoveredUser) -> Bool {
@@ -2771,6 +2776,12 @@ struct DiscoveredAttachment {
let metadata: String
let URLString: String
var image: UIImage?
var isTemporary: Bool {
return image != nil
}
var thumbnailImage: UIImage? {
guard (metadata as NSString).length > 0 else {
@@ -2802,7 +2813,7 @@ struct DiscoveredAttachment {
}
//return DiscoveredAttachment(kind: kind, metadata: metadata, URLString: URLString)
return DiscoveredAttachment(metadata: metadata, URLString: URLString)
return DiscoveredAttachment(metadata: metadata, URLString: URLString, image: nil)
}
}
@@ -2976,6 +2987,8 @@ struct DiscoveredFeed: Hashable {
let groupID: String
var messagesCount: Int
var uploadingErrorMessage: String? = nil
var timeAndDistanceString: String {
let timeString = "\(NSDate(timeIntervalSince1970: createdUnixTime).timeAgo)"
@@ -3081,7 +3094,7 @@ struct DiscoveredFeed: Hashable {
skill = Skill.fromJSONDictionary(skillInfo)
}
return DiscoveredFeed(id: id, allowComment: allowComment, kind: kind, createdUnixTime: createdUnixTime, updatedUnixTime: updatedUnixTime, creator: creator, body: body, attachment: attachment, distance: distance, skill: skill, groupID: groupID, messagesCount: messagesCount)
return DiscoveredFeed(id: id, allowComment: allowComment, kind: kind, createdUnixTime: createdUnixTime, updatedUnixTime: updatedUnixTime, creator: creator, body: body, attachment: attachment, distance: distance, skill: skill, groupID: groupID, messagesCount: messagesCount, uploadingErrorMessage: nil)
}
}
@@ -3228,6 +3241,17 @@ enum FeedKind: String {
default: return nil
}
}
var needBackgroundUpload: Bool {
switch self {
case .Image:
return true
case .Audio:
return true
default:
return false
}
}
}
func createFeedWithKind(kind: FeedKind, message: String, attachments: [JSONDictionary]?, coordinate: CLLocationCoordinate2D?, skill: Skill?, allowComment: Bool, failureHandler: ((Reason, String?) -> Void)?, completion: JSONDictionary -> Void) {
@@ -23,6 +23,15 @@ class FeedsViewController: BaseViewController {
var hideRightBarItem: Bool = false
var uploadingFeeds = [DiscoveredFeed]()
func handleUploadingErrorMessage(message: String) {
if !uploadingFeeds.isEmpty {
uploadingFeeds[0].uploadingErrorMessage = message
feedsTableView.reloadSections(NSIndexSet(index: Section.UploadingFeed.rawValue), withRowAnimation: .None)
println("handleUploadingErrorMessage: \(message)")
}
}
var feeds = [DiscoveredFeed]()
@IBOutlet weak var feedsTableView: UITableView!
@@ -164,7 +173,7 @@ class FeedsViewController: BaseViewController {
}
}
private func updateFeedsTableViewOrInsertWithIndexPaths(indexPaths: [NSIndexPath]?) {
private func updateFeedsTableViewOrInsertWithIndexPaths(indexPaths: [NSIndexPath]?, animation: UITableViewRowAnimation? = nil) {
// refresh skillUsers
@@ -175,7 +184,7 @@ class FeedsViewController: BaseViewController {
if let indexPaths = indexPaths where feeds.count > 1 {
// insert
feedsTableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: .Automatic)
feedsTableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: animation ?? .Automatic)
} else {
// or reload
@@ -624,22 +633,55 @@ class FeedsViewController: BaseViewController {
// MARK: - Navigation
private var newFeedViewController: NewFeedViewController?
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let identifier = segue.identifier else {
return
}
let afterCreatedFeedAction: DiscoveredFeed -> Void = { [weak self] feed in
let beforeUploadingFeedAction: (DiscoveredFeed, NewFeedViewController) -> Void = { [weak self] feed, newFeedViewController in
self?.newFeedViewController = newFeedViewController
dispatch_async(dispatch_get_main_queue()) {
if let strongSelf = self {
strongSelf.feeds.insert(feed, atIndex: 0)
strongSelf.uploadingFeeds.insert(feed, atIndex: 0)
let indexPath = NSIndexPath(forRow: 0, inSection: Section.UploadingFeed.rawValue)
strongSelf.feedsTableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
}
}
let afterCreatedFeedAction: DiscoveredFeed -> Void = { [weak self] feed in
self?.newFeedViewController = nil
dispatch_async(dispatch_get_main_queue()) {
if let strongSelf = self {
strongSelf.feedsTableView.beginUpdates()
var animation: UITableViewRowAnimation = .Automatic
if !strongSelf.uploadingFeeds.isEmpty {
strongSelf.uploadingFeeds = []
strongSelf.feedsTableView.reloadSections(NSIndexSet(index: Section.UploadingFeed.rawValue), withRowAnimation: .None)
animation = .None
}
strongSelf.feeds.insert(feed, atIndex: 0)
let indexPath = NSIndexPath(forRow: 0, inSection: Section.Feed.rawValue)
strongSelf.updateFeedsTableViewOrInsertWithIndexPaths([indexPath])
strongSelf.updateFeedsTableViewOrInsertWithIndexPaths([indexPath], animation: animation)
strongSelf.feedsTableView.endUpdates()
}
}
@@ -647,15 +689,30 @@ class FeedsViewController: BaseViewController {
})
}
let getFeedsViewController: () -> FeedsViewController? = { [weak self] in
return self
}
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)
if let indexPath = sender as? NSIndexPath, section = Section(rawValue: indexPath.section) {
switch section {
case .SkillUsers:
break
case .UploadingFeed:
let discoveredUser = uploadingFeeds[indexPath.row].creator
vc.profileUser = ProfileUser.DiscoveredUserType(discoveredUser)
case .Feed:
let discoveredUser = feeds[indexPath.row].creator
vc.profileUser = ProfileUser.DiscoveredUserType(discoveredUser)
case .LoadMore:
break
}
}
vc.fromType = .None
@@ -677,8 +734,18 @@ class FeedsViewController: BaseViewController {
let vc = segue.destinationViewController as! FeedsViewController
if let indexPath = sender as? NSIndexPath {
vc.skill = feeds[indexPath.row].skill
if let indexPath = sender as? NSIndexPath, section = Section(rawValue: indexPath.section) {
switch section {
case .SkillUsers:
break
case .UploadingFeed:
vc.skill = uploadingFeeds[indexPath.row].skill
case .Feed:
vc.skill = feeds[indexPath.row].skill
case .LoadMore:
break
}
}
vc.hidesBottomBarWhenPushed = true
@@ -744,7 +811,9 @@ class FeedsViewController: BaseViewController {
vc.preparedSkill = skill
vc.beforeUploadingFeedAction = beforeUploadingFeedAction
vc.afterCreatedFeedAction = afterCreatedFeedAction
vc.getFeedsViewController = getFeedsViewController
case "presentNewFeedVoiceRecord":
@@ -757,7 +826,9 @@ class FeedsViewController: BaseViewController {
vc.preparedSkill = skill
vc.beforeUploadingFeedAction = beforeUploadingFeedAction
vc.afterCreatedFeedAction = afterCreatedFeedAction
vc.getFeedsViewController = getFeedsViewController
case "presentPickLocation":
@@ -835,39 +906,41 @@ extension FeedsViewController: UITableViewDataSource, UITableViewDelegate {
private enum Section: Int {
case SkillUsers
case UploadingFeed
case Feed
case LoadMore
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
return 4
}
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:
guard let section = Section(rawValue: section) else {
return 0
}
switch section {
case .SkillUsers:
return (skill == nil) ? 0 : 1
case .UploadingFeed:
return uploadingFeeds.count
case .Feed:
return feeds.count
case .LoadMore:
return feeds.isEmpty ? 0 : 1
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch indexPath.section {
guard let section = Section(rawValue: indexPath.section) else {
return UITableViewCell()
}
case Section.SkillUsers.rawValue:
let cell = tableView.dequeueReusableCellWithIdentifier(feedSkillUsersCellID) as! FeedSkillUsersCell
return cell
case Section.Feed.rawValue:
let feed = feeds[indexPath.row]
func cellForFeed(feed: DiscoveredFeed) -> UITableViewCell {
switch feed.kind {
@@ -909,38 +982,47 @@ extension FeedsViewController: UITableViewDataSource, UITableViewDelegate {
let cell = tableView.dequeueReusableCellWithIdentifier(feedBasicCellID) as! FeedBasicCell
return cell
}
}
case Section.LoadMore.rawValue:
let cell = tableView.dequeueReusableCellWithIdentifier(loadMoreTableViewCellID) as! LoadMoreTableViewCell
switch section {
case .SkillUsers:
let cell = tableView.dequeueReusableCellWithIdentifier(feedSkillUsersCellID) as! FeedSkillUsersCell
return cell
default:
return UITableViewCell()
case .UploadingFeed:
let feed = uploadingFeeds[indexPath.row]
return cellForFeed(feed)
case .Feed:
let feed = feeds[indexPath.row]
return cellForFeed(feed)
case .LoadMore:
let cell = tableView.dequeueReusableCellWithIdentifier(loadMoreTableViewCellID) as! LoadMoreTableViewCell
return cell
}
}
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
switch indexPath.section {
guard let section = Section(rawValue: indexPath.section) else {
return
}
case Section.SkillUsers.rawValue:
guard let cell = cell as? FeedSkillUsersCell else {
break
}
cell.configureWithFeeds(feeds)
case Section.Feed.rawValue:
let feed = feeds[indexPath.row]
func configureFeedCell(cell: UITableViewCell, withFeed feed: DiscoveredFeed) {
guard let cell = cell as? FeedBasicCell else {
break
return
}
cell.tapAvatarAction = { [weak self] cell in
if let indexPath = tableView.indexPathForCell(cell) { // indexPath
println("tapAvatarAction indexPath: \(indexPath.section), \(indexPath.row)")
self?.performSegueWithIdentifier("showProfile", sender: indexPath)
}
}
@@ -1190,8 +1272,52 @@ extension FeedsViewController: UITableViewDataSource, UITableViewDelegate {
default:
break
}
}
case Section.LoadMore.rawValue:
switch section {
case .SkillUsers:
guard let cell = cell as? FeedSkillUsersCell else {
break
}
cell.configureWithFeeds(feeds)
case .UploadingFeed:
let feed = uploadingFeeds[indexPath.row]
configureFeedCell(cell, withFeed: feed)
if let cell = cell as? FeedBasicCell {
cell.retryUploadingFeedAction = { [weak self] cell in
self?.newFeedViewController?.post(again: true)
if let indexPath = self?.feedsTableView.indexPathForCell(cell) {
self?.uploadingFeeds[indexPath.row].uploadingErrorMessage = nil
cell.hasUploadingErrorMessage = false
}
}
cell.deleteUploadingFeedAction = { [weak self] cell in
if let indexPath = self?.feedsTableView.indexPathForCell(cell) {
self?.uploadingFeeds.removeAtIndex(indexPath.row)
self?.feedsTableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
self?.newFeedViewController = nil
}
}
}
case .Feed:
let feed = feeds[indexPath.row]
configureFeedCell(cell, withFeed: feed)
case .LoadMore:
guard let cell = cell as? LoadMoreTableViewCell else {
break
@@ -1206,28 +1332,30 @@ extension FeedsViewController: UITableViewDataSource, UITableViewDelegate {
updateFeeds(mode: .LoadMore, finish: { [weak cell] in
cell?.loadingActivityIndicator.stopAnimating()
})
default:
break
}
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
switch indexPath.section {
guard let section = Section(rawValue: indexPath.section) else {
return 0
}
case Section.SkillUsers.rawValue:
switch section {
case .SkillUsers:
return 70
case Section.Feed.rawValue:
case .UploadingFeed:
let feed = uploadingFeeds[indexPath.row]
return FeedsViewController.layoutPool.heightOfFeed(feed)
case .Feed:
let feed = feeds[indexPath.row]
return FeedsViewController.layoutPool.heightOfFeed(feed)
case Section.LoadMore.rawValue:
case .LoadMore:
return 60
default:
return 0
}
}
@@ -1241,15 +1369,22 @@ extension FeedsViewController: UITableViewDataSource, UITableViewDelegate {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
switch indexPath.section {
guard let section = Section(rawValue: indexPath.section) else {
return
}
case Section.SkillUsers.rawValue:
switch section {
case .SkillUsers:
performSegueWithIdentifier("showSkillHome", sender: nil)
case Section.Feed.rawValue:
case .UploadingFeed:
break
case .Feed:
performSegueWithIdentifier("showConversation", sender: indexPath)
default:
case .LoadMore:
break
}
}
@@ -1258,12 +1393,19 @@ extension FeedsViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
switch indexPath.section {
guard let section = Section(rawValue: indexPath.section) else {
return false
}
case Section.SkillUsers.rawValue:
switch section {
case .SkillUsers:
return false
case Section.Feed.rawValue:
case .UploadingFeed:
return false
case .Feed:
let feed = feeds[indexPath.item]
if feed.creator.id == YepUserDefaults.userID.value {
return false
@@ -1271,23 +1413,32 @@ extension FeedsViewController: UITableViewDataSource, UITableViewDelegate {
return true
}
default:
case .LoadMore:
return false
}
}
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let reportAction = UITableViewRowAction(style: .Default, title: NSLocalizedString("Report", comment: "")) { [weak self] action, indexPath in
if let feed = self?.feeds[indexPath.row] {
self?.report(.Feed(feed))
}
tableView.setEditing(false, animated: true)
guard let section = Section(rawValue: indexPath.section) else {
return nil
}
return [reportAction]
if case .Feed = section {
let reportAction = UITableViewRowAction(style: .Default, title: NSLocalizedString("Report", comment: "")) { [weak self] action, indexPath in
if let feed = self?.feeds[indexPath.row] {
self?.report(.Feed(feed))
}
tableView.setEditing(false, animated: true)
}
return [reportAction]
}
return nil
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
@@ -49,10 +49,14 @@ class NewFeedViewController: SegueViewController {
var attachment: Attachment = .Default
var beforeUploadingFeedAction: ((feed: DiscoveredFeed, newFeedViewController: NewFeedViewController) -> Void)?
var afterCreatedFeedAction: ((feed: DiscoveredFeed) -> Void)?
var preparedSkill: Skill?
weak var feedsViewController: FeedsViewController?
var getFeedsViewController: (() -> FeedsViewController?)?
@IBOutlet private weak var feedWhiteBGView: UIView!
@@ -159,15 +163,20 @@ class NewFeedViewController: SegueViewController {
case .Uploading:
postButton.enabled = false
messageTextView.resignFirstResponder()
YepHUD.showActivityIndicator()
//YepHUD.showActivityIndicator()
case .Failed(let message):
YepHUD.hideActivityIndicator()
//YepHUD.hideActivityIndicator()
postButton.enabled = true
YepAlert.alertSorry(message: message, inViewController: self)
if presentingViewController != nil {
YepAlert.alertSorry(message: message, inViewController: self)
} else {
feedsViewController?.handleUploadingErrorMessage(message)
}
case .Success:
YepHUD.hideActivityIndicator()
//YepHUD.hideActivityIndicator()
messageTextView.text = nil
}
}
@@ -200,6 +209,10 @@ class NewFeedViewController: SegueViewController {
choosePromptLabel.hidden = (newValue != nil)
}
}
deinit {
println("NewFeed deinit")
}
override func viewDidLoad() {
super.viewDidLoad()
@@ -216,6 +229,9 @@ class NewFeedViewController: SegueViewController {
}
view.sendSubviewToBack(feedWhiteBGView)
feedsViewController = getFeedsViewController?()
println("feedsViewController: \(feedsViewController)")
isDirty = false
@@ -530,13 +546,96 @@ class NewFeedViewController: SegueViewController {
self.dismissViewControllerAnimated(true, completion: nil)
}
private struct UploadImageInfo {
let s3UploadParams: S3UploadParams
let metaDataString: String?
// private struct UploadImageInfo {
//
// let s3UploadParams: S3UploadParams
// let metaDataString: String?
// }
func tryMakeUploadingFeed() -> DiscoveredFeed? {
guard let
myUserID = YepUserDefaults.userID.value,
realm = try? Realm(),
me = userWithUserID(myUserID, inRealm: realm) else {
return nil
}
let creator = DiscoveredUser.fromUser(me)
var kind: FeedKind = .Text
let createdUnixTime = NSDate().timeIntervalSince1970
let updatedUnixTime = createdUnixTime
let message = messageTextView.text.trimming(.WhitespaceAndNewline)
var feedAttachment: DiscoveredFeed.Attachment?
switch attachment {
case .Default:
if !mediaImages.isEmpty {
kind = .Image
let imageAttachments: [DiscoveredAttachment] = mediaImages.map({ image in
let imageWidth = image.size.width
let imageHeight = image.size.height
let fixedImageWidth: CGFloat
let fixedImageHeight: CGFloat
if imageWidth > imageHeight {
fixedImageWidth = min(imageWidth, YepConfig.Media.miniImageWidth)
fixedImageHeight = imageHeight * (fixedImageWidth / imageWidth)
} else {
fixedImageHeight = min(imageHeight, YepConfig.Media.miniImageHeight)
fixedImageWidth = imageWidth * (fixedImageHeight / imageHeight)
}
let fixedSize = CGSize(width: fixedImageWidth, height: fixedImageHeight)
// resize to smaller, not need fixRotation
if let image = image.resizeToSize(fixedSize, withInterpolationQuality: .Medium) {
return DiscoveredAttachment(metadata: "", URLString: "", image: image)
} else {
return nil
}
}).flatMap({ $0 })
feedAttachment = .Images(imageAttachments)
}
case .Voice(let feedVoice):
kind = .Audio
let audioAsset = AVURLAsset(URL: feedVoice.fileURL, options: nil)
let audioDuration = CMTimeGetSeconds(audioAsset.duration) as Double
let audioMetaDataInfo = [YepConfig.MetaData.audioSamples: feedVoice.limitedSampleValues, YepConfig.MetaData.audioDuration: audioDuration]
let audioMetaData = try! NSJSONSerialization.dataWithJSONObject(audioMetaDataInfo, options: [])
let audioInfo = DiscoveredFeed.AudioInfo(feedID: "", URLString: "", metaData: audioMetaData, duration: audioDuration, sampleValues: feedVoice.limitedSampleValues)
feedAttachment = .Audio(audioInfo)
default:
break
}
return DiscoveredFeed(id: "", allowComment: true, kind: kind, createdUnixTime: createdUnixTime, updatedUnixTime: updatedUnixTime, creator: creator, body: message, attachment: feedAttachment, distance: 0, skill: nil, groupID: "", messagesCount: 0, uploadingErrorMessage: nil)
}
@objc private func post(sender: UIBarButtonItem) {
post(again: false)
}
func post(again again: Bool) {
let messageLength = (messageTextView.text as NSString).length
@@ -546,7 +645,15 @@ class NewFeedViewController: SegueViewController {
return
}
if !again {
if let feed = tryMakeUploadingFeed() where feed.kind.needBackgroundUpload {
beforeUploadingFeedAction?(feed: feed, newFeedViewController: self)
dismissViewControllerAnimated(true, completion: nil)
}
}
uploadState = .Uploading
let message = messageTextView.text.trimming(.WhitespaceAndNewline)
@@ -574,7 +681,7 @@ class NewFeedViewController: SegueViewController {
}
}, completion: { data in
println(data)
println("createFeedWithKind: \(data)")
dispatch_async(dispatch_get_main_queue()) { [weak self] in
@@ -584,7 +691,9 @@ class NewFeedViewController: SegueViewController {
self?.afterCreatedFeedAction?(feed: feed)
}
self?.dismissViewControllerAnimated(true, completion: nil)
if !kind.needBackgroundUpload {
self?.dismissViewControllerAnimated(true, completion: nil)
}
}
syncGroupsAndDoFurtherAction {}
@@ -13,7 +13,9 @@ class NewFeedVoiceRecordViewController: SegueViewController {
var preparedSkill: Skill?
var beforeUploadingFeedAction: ((feed: DiscoveredFeed, newFeedViewController: NewFeedViewController) -> Void)?
var afterCreatedFeedAction: ((feed: DiscoveredFeed) -> Void)?
var getFeedsViewController: (() -> FeedsViewController?)?
@IBOutlet private weak var nextButton: UIBarButtonItem!
@@ -429,7 +431,9 @@ class NewFeedVoiceRecordViewController: SegueViewController {
vc.preparedSkill = preparedSkill
vc.beforeUploadingFeedAction = beforeUploadingFeedAction
vc.afterCreatedFeedAction = afterCreatedFeedAction
vc.getFeedsViewController = getFeedsViewController
}
default:
@@ -156,6 +156,10 @@ extension FeedAnyImagesCell: UICollectionViewDataSource, UICollectionViewDelegat
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
guard let firstAttachment = attachments.first where !firstAttachment.isTemporary else {
return
}
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! FeedMediaCell
let transitionView = cell.imageView
+46 -2
View File
@@ -124,6 +124,20 @@ class FeedBasicCell: UITableViewCell {
return imageView
}()
lazy var uploadingErrorContainerView: FeedUploadingErrorContainerView = {
let view = FeedUploadingErrorContainerView(frame: CGRect(x: 0, y: 0, width: 200, height: 30))
return view
}()
var hasUploadingErrorMessage = false {
didSet {
uploadingErrorContainerView.hidden = !hasUploadingErrorMessage
leftBottomLabel.hidden = hasUploadingErrorMessage
messageCountLabel.hidden = hasUploadingErrorMessage
discussionImageView.hidden = hasUploadingErrorMessage
}
}
var feed: DiscoveredFeed?
var tapAvatarAction: (UITableViewCell -> Void)?
@@ -133,6 +147,9 @@ class FeedBasicCell: UITableViewCell {
var touchesEndedAction: (UITableViewCell -> Void)?
var touchesCancelledAction: (UITableViewCell -> Void)?
var retryUploadingFeedAction: ((cell: FeedBasicCell) -> Void)?
var deleteUploadingFeedAction: ((cell: FeedBasicCell) -> Void)?
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
@@ -162,7 +179,7 @@ class FeedBasicCell: UITableViewCell {
let rect = feed.body.boundingRectWithSize(CGSize(width: FeedBasicCell.messageTextViewMaxWidth, height: CGFloat(FLT_MAX)), options: [.UsesLineFragmentOrigin, .UsesFontLeading], attributes: YepConfig.FeedBasicCell.textAttributes, context: nil)
let height: CGFloat = ceil(rect.height) + 10 + 40 + 4 + 15 + 17 + 15
let height: CGFloat = 10 + 40 + ceil(rect.height) + 4 + 15 + 17 + 15
return ceil(height)
}
@@ -250,7 +267,7 @@ class FeedBasicCell: UITableViewCell {
discussionImageView.frame = basicLayout.discussionImageViewFrame
} else {
leftBottomLabel.frame.origin.y = contentView.bounds.height - leftBottomLabel.frame.height - 10
leftBottomLabel.frame.origin.y = contentView.bounds.height - leftBottomLabel.frame.height - 15
let rect = messagesCountString.boundingRectWithSize(CGSize(width: 320, height: CGFloat(FLT_MAX)), options: [.UsesLineFragmentOrigin, .UsesFontLeading], attributes: YepConfig.FeedBasicCell.bottomLabelsTextAttributes, context: nil)
@@ -271,6 +288,33 @@ class FeedBasicCell: UITableViewCell {
layoutCache.update(layout: newLayout)
}
do {
if let message = feed.uploadingErrorMessage {
hasUploadingErrorMessage = true
let y = leftBottomLabel.frame.origin.y - (30 - leftBottomLabel.frame.height) * 0.5
uploadingErrorContainerView.frame = CGRect(x: 65, y: y, width: screenWidth - 65, height: 30)
uploadingErrorContainerView.errorMessageLabel.text = message
uploadingErrorContainerView.retryAction = { [weak self] in
if let strongSelf = self {
strongSelf.retryUploadingFeedAction?(cell: strongSelf)
}
}
uploadingErrorContainerView.deleteAction = { [weak self] in
if let strongSelf = self {
strongSelf.deleteUploadingFeedAction?(cell: strongSelf)
}
}
contentView.addSubview(uploadingErrorContainerView)
} else {
hasUploadingErrorMessage = false
}
}
}
// MARK: Actions
+11 -2
View File
@@ -71,8 +71,13 @@ class FeedBiggerImageCell: FeedBasicCell {
}
if let onlyAttachment = feed.imageAttachments?.first {
biggerImageView.yep_showActivityIndicatorWhenLoading = true
biggerImageView.yep_setImageOfAttachment(onlyAttachment, withSize: YepConfig.FeedBiggerImageCell.imageSize)
if onlyAttachment.isTemporary {
biggerImageView.image = onlyAttachment.image
} else {
biggerImageView.yep_showActivityIndicatorWhenLoading = true
biggerImageView.yep_setImageOfAttachment(onlyAttachment, withSize: YepConfig.FeedBiggerImageCell.imageSize)
}
}
if layoutCache.layout == nil {
@@ -88,6 +93,10 @@ class FeedBiggerImageCell: FeedBasicCell {
@objc private func tap(sender: UITapGestureRecognizer) {
guard let firstAttachment = feed?.imageAttachments?.first where !firstAttachment.isTemporary else {
return
}
if let attachments = feed?.imageAttachments {
tapMediaAction?(transitionView: biggerImageView, image: biggerImageView.image, attachments: attachments, index: 0)
}
+1 -1
View File
@@ -183,7 +183,7 @@ struct FeedCellLayout {
let messageTextViewHeight = ceil(_rect1.height)
let messageTextViewFrame = CGRect(x: 65, y: 54, width: screenWidth - 65 - 15, height: messageTextViewHeight)
let leftBottomLabelOriginY = height - 17 - 10
let leftBottomLabelOriginY = height - 17 - 15
let leftBottomLabelFrame = CGRect(x: 65, y: leftBottomLabelOriginY, width: 200, height: 17)
let messagesCountString = "\(feed.messagesCount)"
@@ -112,8 +112,14 @@ class FeedNormalImagesCell: FeedBasicCell {
for i in 0..<imageViews.count {
if let attachment = attachments[safe: i] {
imageViews[i].yep_showActivityIndicatorWhenLoading = true
imageViews[i].yep_setImageOfAttachment(attachment, withSize: YepConfig.FeedNormalImagesCell.imageSize)
if attachment.isTemporary {
imageViews[i].image = attachment.image
} else {
imageViews[i].yep_showActivityIndicatorWhenLoading = true
imageViews[i].yep_setImageOfAttachment(attachment, withSize: YepConfig.FeedNormalImagesCell.imageSize)
}
imageViews[i].hidden = false
@@ -136,6 +142,10 @@ class FeedNormalImagesCell: FeedBasicCell {
@objc private func tap(sender: UITapGestureRecognizer) {
guard let firstAttachment = feed?.imageAttachments?.first where !firstAttachment.isTemporary else {
return
}
if let imageView = sender.view as? UIImageView, index = imageViews.indexOf(imageView) {
if let attachments = feed?.imageAttachments {
@@ -64,7 +64,7 @@ class FeedConversationCell: UITableViewCell {
let attachments = feed.attachments.map({
//DiscoveredAttachment(kind: AttachmentKind(rawValue: $0.kind)!, metadata: $0.metadata, URLString: $0.URLString)
DiscoveredAttachment( metadata: $0.metadata, URLString: $0.URLString)
DiscoveredAttachment(metadata: $0.metadata, URLString: $0.URLString, image: nil)
})
mediaView.setImagesWithAttachments(attachments)
@@ -38,10 +38,15 @@ class FeedMediaCell: UICollectionViewCell {
func configureWithAttachment(attachment: DiscoveredAttachment, bigger: Bool) {
let size = bigger ? feedAttachmentBiggerImageSize : feedAttachmentImageSize
if attachment.isTemporary {
imageView.image = attachment.image
imageView.yep_showActivityIndicatorWhenLoading = true
imageView.yep_setImageOfAttachment(attachment, withSize: size)
} else {
let size = bigger ? feedAttachmentBiggerImageSize : feedAttachmentImageSize
imageView.yep_showActivityIndicatorWhenLoading = true
imageView.yep_setImageOfAttachment(attachment, withSize: size)
}
deleteImageView.hidden = true
}
@@ -0,0 +1,115 @@
//
// FeedUploadingErrorContainerView.swift
// Yep
//
// Created by nixzhu on 16/1/6.
// Copyright © 2016 Catch Inc. All rights reserved.
//
import UIKit
class FeedUploadingErrorContainerView: UIView {
var retryAction: (() -> Void)?
var deleteAction: (() -> Void)?
lazy var leftContainerView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(red: 1, green: 56/255.0, blue: 36/255.0, alpha: 0.1)
view.layer.cornerRadius = 5
return view
}()
lazy var iconImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "icon_topic_reddot"))
return imageView
}()
lazy var errorMessageLabel: UILabel = {
let label = UILabel()
label.text = NSLocalizedString("Upload failed!", comment: "")
label.textColor = UIColor.redColor()
return label
}()
lazy var retryButton: UIButton = {
let button = UIButton()
button.setTitle(NSLocalizedString("Retry", comment: ""), forState: .Normal)
button.setTitleColor(UIColor.yepTintColor(), forState: .Normal)
button.addTarget(self, action: "retryUploadingFeed:", forControlEvents: .TouchUpInside)
return button
}()
lazy var deleteButton: UIButton = {
let button = UIButton()
button.setTitle(NSLocalizedString("Delete", comment: ""), forState: .Normal)
button.setTitleColor(UIColor.redColor(), forState: .Normal)
button.addTarget(self, action: "deleteUploadingFeed:", forControlEvents: .TouchUpInside)
return button
}()
override func didMoveToSuperview() {
super.didMoveToSuperview()
makeUI()
}
func makeUI() {
//backgroundColor = UIColor.whiteColor()
do {
addSubview(leftContainerView)
addSubview(deleteButton)
leftContainerView.translatesAutoresizingMaskIntoConstraints = false
deleteButton.translatesAutoresizingMaskIntoConstraints = false
let views = [
"leftContainerView": leftContainerView,
"deleteButton": deleteButton,
]
let constraintsH = NSLayoutConstraint.constraintsWithVisualFormat("H:|[leftContainerView]-15-[deleteButton]-15-|", options: [.AlignAllCenterY], metrics: nil, views: views)
let constraintsV = NSLayoutConstraint.constraintsWithVisualFormat("V:|[leftContainerView]|", options: [], metrics: nil, views: views)
NSLayoutConstraint.activateConstraints(constraintsH)
NSLayoutConstraint.activateConstraints(constraintsV)
}
do {
leftContainerView.addSubview(iconImageView)
leftContainerView.addSubview(errorMessageLabel)
leftContainerView.addSubview(retryButton)
iconImageView.translatesAutoresizingMaskIntoConstraints = false
errorMessageLabel.translatesAutoresizingMaskIntoConstraints = false
retryButton.translatesAutoresizingMaskIntoConstraints = false
let views = [
"iconImageView": iconImageView,
"errorMessageLabel": errorMessageLabel,
"retryButton": retryButton,
]
let constraintsH = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[iconImageView]-[errorMessageLabel]-[retryButton]-|", options: [.AlignAllCenterY], metrics: nil, views: views)
iconImageView.setContentHuggingPriority(UILayoutPriorityRequired, forAxis: .Horizontal)
iconImageView.setContentCompressionResistancePriority(UILayoutPriorityRequired, forAxis: .Horizontal)
let iconImageViewCenterY = NSLayoutConstraint(item: iconImageView, attribute: .CenterY, relatedBy: .Equal, toItem: leftContainerView, attribute: .CenterY, multiplier: 1.0, constant: 0)
NSLayoutConstraint.activateConstraints(constraintsH)
NSLayoutConstraint.activateConstraints([iconImageViewCenterY])
}
}
@objc private func retryUploadingFeed(sender: UIButton) {
retryAction?()
}
@objc private func deleteUploadingFeed(sender: UIButton) {
deleteAction?()
}
}
+1 -1
View File
@@ -298,7 +298,7 @@ class FeedView: UIView {
attachments = feed.attachments.map({
//DiscoveredAttachment(kind: AttachmentKind(rawValue: $0.kind)!, metadata: $0.metadata, URLString: $0.URLString)
DiscoveredAttachment(metadata: $0.metadata, URLString: $0.URLString)
DiscoveredAttachment(metadata: $0.metadata, URLString: $0.URLString, image: nil)
})
messageLabelTrailingConstraint.constant = attachments.isEmpty ? 15 : 60
+2
View File
@@ -728,3 +728,5 @@
"Recalled by creator." = "消息已被撤回。";
"Retry" = "重试";