diff --git a/.swiftlint.yml b/.swiftlint.yml index 0b649144a..f97b4fac3 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -6,6 +6,4 @@ disabled_rules: # rule identifiers to exclude from running - todo - type_body_length - variable_name - - variable_name_min_length - - variable_name_max_length - type_name diff --git a/AUTHORS b/AUTHORS index 13a54dc09..ee798ee0f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3,6 +3,7 @@ Diego Sánchez Anton Schukin +Zhao Wang &yet LLC Badoo \ No newline at end of file diff --git a/ChattoApp/ChattoApp.xcodeproj/project.pbxproj b/ChattoApp/ChattoApp.xcodeproj/project.pbxproj index 984b7e8db..ad3b56e7a 100644 --- a/ChattoApp/ChattoApp.xcodeproj/project.pbxproj +++ b/ChattoApp/ChattoApp.xcodeproj/project.pbxproj @@ -12,6 +12,9 @@ C33FBFB01BDE441C008E3545 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C33FBFAF1BDE441C008E3545 /* Assets.xcassets */; }; C33FBFB31BDE441C008E3545 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C33FBFB11BDE441C008E3545 /* LaunchScreen.storyboard */; }; C33FBFC91BDE441C008E3545 /* ChattoAppUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FBFC81BDE441C008E3545 /* ChattoAppUITests.swift */; }; + C341D42E1C9635DF00FD3463 /* TimeSeparatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C341D42B1C9635DF00FD3463 /* TimeSeparatorModel.swift */; }; + C341D42F1C9635DF00FD3463 /* TimeSeparatorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C341D42C1C9635DF00FD3463 /* TimeSeparatorPresenter.swift */; }; + C341D4301C9635DF00FD3463 /* TimeSeparatorCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C341D42D1C9635DF00FD3463 /* TimeSeparatorCollectionViewCell.swift */; }; C35A6F4F1BF807EC0085CA19 /* SlidingDataSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35A6F4E1BF807EC0085CA19 /* SlidingDataSourceTests.swift */; }; C3F91DB61C75EF9E00D461D2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F91DA01C75EF9E00D461D2 /* AppDelegate.swift */; }; C3F91DB71C75EF9E00D461D2 /* ChatItemsDemoDecorator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F91DA11C75EF9E00D461D2 /* ChatItemsDemoDecorator.swift */; }; @@ -31,7 +34,6 @@ C3F91DCC1C75EFE300D461D2 /* SendingStatusCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F91DC91C75EFE300D461D2 /* SendingStatusCollectionViewCell.swift */; }; C3F91DCD1C75EFE300D461D2 /* SendingStatusCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = C3F91DCA1C75EFE300D461D2 /* SendingStatusCollectionViewCell.xib */; }; C3F91DCE1C75EFE300D461D2 /* SendingStatusPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F91DCB1C75EFE300D461D2 /* SendingStatusPresenter.swift */; }; - FE1A697B1C93FF10004DF45A /* TimestampSeparatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE1A697A1C93FF10004DF45A /* TimestampSeparatorView.swift */; }; FE2D050B1C915ADB006F902B /* BaseMessageCollectionViewCellAvatarStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE2D050A1C915ADB006F902B /* BaseMessageCollectionViewCellAvatarStyle.swift */; }; /* End PBXBuildFile section */ @@ -79,6 +81,9 @@ C33FBFC41BDE441C008E3545 /* ChattoAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ChattoAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; C33FBFC81BDE441C008E3545 /* ChattoAppUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChattoAppUITests.swift; sourceTree = ""; }; C33FBFCA1BDE441C008E3545 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C341D42B1C9635DF00FD3463 /* TimeSeparatorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TimeSeparatorModel.swift; path = "Time Separator/TimeSeparatorModel.swift"; sourceTree = ""; }; + C341D42C1C9635DF00FD3463 /* TimeSeparatorPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TimeSeparatorPresenter.swift; path = "Time Separator/TimeSeparatorPresenter.swift"; sourceTree = ""; }; + C341D42D1C9635DF00FD3463 /* TimeSeparatorCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TimeSeparatorCollectionViewCell.swift; path = "Time Separator/TimeSeparatorCollectionViewCell.swift"; sourceTree = ""; }; C35A6F4E1BF807EC0085CA19 /* SlidingDataSourceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlidingDataSourceTests.swift; sourceTree = ""; }; C3F91DA01C75EF9E00D461D2 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C3F91DA11C75EF9E00D461D2 /* ChatItemsDemoDecorator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatItemsDemoDecorator.swift; sourceTree = ""; }; @@ -98,7 +103,6 @@ C3F91DC91C75EFE300D461D2 /* SendingStatusCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendingStatusCollectionViewCell.swift; sourceTree = ""; }; C3F91DCA1C75EFE300D461D2 /* SendingStatusCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SendingStatusCollectionViewCell.xib; sourceTree = ""; }; C3F91DCB1C75EFE300D461D2 /* SendingStatusPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendingStatusPresenter.swift; sourceTree = ""; }; - FE1A697A1C93FF10004DF45A /* TimestampSeparatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimestampSeparatorView.swift; sourceTree = ""; }; FE2D050A1C915ADB006F902B /* BaseMessageCollectionViewCellAvatarStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseMessageCollectionViewCellAvatarStyle.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -197,6 +201,16 @@ path = ChattoAppUITests; sourceTree = ""; }; + C341D42A1C96359000FD3463 /* Time Separator */ = { + isa = PBXGroup; + children = ( + C341D42B1C9635DF00FD3463 /* TimeSeparatorModel.swift */, + C341D42C1C9635DF00FD3463 /* TimeSeparatorPresenter.swift */, + C341D42D1C9635DF00FD3463 /* TimeSeparatorCollectionViewCell.swift */, + ); + name = "Time Separator"; + sourceTree = ""; + }; C3F91D9F1C75EF9E00D461D2 /* Source */ = { isa = PBXGroup; children = ( @@ -212,8 +226,8 @@ C3F91DAC1C75EF9E00D461D2 /* Photo Messages */, C3F91DC81C75EFE300D461D2 /* Sending status */, C3F91DB11C75EF9E00D461D2 /* Text Messages */, + C341D42A1C96359000FD3463 /* Time Separator */, FE2D050A1C915ADB006F902B /* BaseMessageCollectionViewCellAvatarStyle.swift */, - FE1A697A1C93FF10004DF45A /* TimestampSeparatorView.swift */, ); path = Source; sourceTree = ""; @@ -453,11 +467,12 @@ C3F91DC31C75EF9E00D461D2 /* SlidingDatasSource.swift in Sources */, C3F91DC71C75EF9E00D461D2 /* BaseMessageHandler.swift in Sources */, C3F91DC61C75EF9E00D461D2 /* DemoTextMessageViewModel.swift in Sources */, + C341D42E1C9635DF00FD3463 /* TimeSeparatorModel.swift in Sources */, C3F91DC01C75EF9E00D461D2 /* DemoPhotoMessageHandler.swift in Sources */, C3F91DBC1C75EF9E00D461D2 /* DemoChatViewController.swift in Sources */, - FE1A697B1C93FF10004DF45A /* TimestampSeparatorView.swift in Sources */, C3F91DBD1C75EF9E00D461D2 /* FakeDataSource.swift in Sources */, C3F91DB61C75EF9E00D461D2 /* AppDelegate.swift in Sources */, + C341D42F1C9635DF00FD3463 /* TimeSeparatorPresenter.swift in Sources */, C3F91DCE1C75EFE300D461D2 /* SendingStatusPresenter.swift in Sources */, C3F91DC51C75EF9E00D461D2 /* DemoTextMessageModel.swift in Sources */, C3F91DCC1C75EFE300D461D2 /* SendingStatusCollectionViewCell.swift in Sources */, @@ -465,6 +480,7 @@ C3F91DC11C75EF9E00D461D2 /* DemoPhotoMessageModel.swift in Sources */, C3F91DC21C75EF9E00D461D2 /* DemoPhotoMessageViewModel.swift in Sources */, C3F91DBE1C75EF9E00D461D2 /* FakeMessageFactory.swift in Sources */, + C341D4301C9635DF00FD3463 /* TimeSeparatorCollectionViewCell.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ChattoApp/ChattoApp/Source/BaseMessageCollectionViewCellAvatarStyle.swift b/ChattoApp/ChattoApp/Source/BaseMessageCollectionViewCellAvatarStyle.swift index 35c46fc44..4ac768e01 100644 --- a/ChattoApp/ChattoApp/Source/BaseMessageCollectionViewCellAvatarStyle.swift +++ b/ChattoApp/ChattoApp/Source/BaseMessageCollectionViewCellAvatarStyle.swift @@ -1,25 +1,25 @@ /* -The MIT License (MIT) + The MIT License (MIT) -Copyright (c) 2016-present Zhao Wang. + Copyright (c) 2015-present Badoo Trading Limited. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ import Foundation diff --git a/ChattoApp/ChattoApp/Source/ChatItemsDemoDecorator.swift b/ChattoApp/ChattoApp/Source/ChatItemsDemoDecorator.swift index ba7a8db02..3e4a3c123 100644 --- a/ChattoApp/ChattoApp/Source/ChatItemsDemoDecorator.swift +++ b/ChattoApp/ChattoApp/Source/ChatItemsDemoDecorator.swift @@ -35,6 +35,7 @@ final class ChatItemsDemoDecorator: ChatItemsDecoratorProtocol { func decorateItems(chatItems: [ChatItemProtocol]) -> [DecoratedChatItem] { var decoratedChatItems = [DecoratedChatItem]() + let calendar = NSCalendar.currentCalendar() for (index, chatItem) in chatItems.enumerate() { let next: ChatItemProtocol? = (index + 1 < chatItems.count) ? chatItems[index + 1] : nil @@ -44,7 +45,7 @@ final class ChatItemsDemoDecorator: ChatItemsDecoratorProtocol { var showsTail = false var additionalItems = [DecoratedChatItem]() - var showWeekDayDateStamp = false + var addTimeSeparator = false if let currentMessage = chatItem as? MessageModelProtocol { if let nextMessage = next as? MessageModelProtocol { showsTail = currentMessage.senderId != nextMessage.senderId @@ -52,10 +53,10 @@ final class ChatItemsDemoDecorator: ChatItemsDecoratorProtocol { showsTail = true } - if let prevMsg = prev as? MessageModelProtocol { - showWeekDayDateStamp = NSCalendar.currentCalendar().compareDate(currentMessage.date, toDate: prevMsg.date, toUnitGranularity: NSCalendarUnit.Day) != NSComparisonResult.OrderedSame + if let previousMessage = prev as? MessageModelProtocol { + addTimeSeparator = calendar.compareDate(currentMessage.date, toDate: previousMessage.date, toUnitGranularity: NSCalendarUnit.Day) != NSComparisonResult.OrderedSame } else { - showWeekDayDateStamp = true + addTimeSeparator = true } if self.showsStatusForMessage(currentMessage) { @@ -66,14 +67,12 @@ final class ChatItemsDemoDecorator: ChatItemsDecoratorProtocol { ) } - if showWeekDayDateStamp { - let dateTimeStamp = DecoratedChatItem(chatItem: WeekDayDatestamp(date: currentMessage.date), decorationAttributes: ChatItemDecorationAttributes(bottomMargin: 0, showsTail: false)) + if addTimeSeparator { + let dateTimeStamp = DecoratedChatItem(chatItem: TimeSeparatorModel(uid: "\(currentMessage.uid)-time-separator", date: currentMessage.date.toWeekDayAndDateString()), decorationAttributes: nil) decoratedChatItems.append(dateTimeStamp) } } - - decoratedChatItems.append(DecoratedChatItem( chatItem: chatItem, decorationAttributes: ChatItemDecorationAttributes(bottomMargin: bottomMargin, showsTail: showsTail)) diff --git a/ChattoApp/ChattoApp/Source/DemoChatViewController.swift b/ChattoApp/ChattoApp/Source/DemoChatViewController.swift index 8381bedc3..39b42e1b2 100644 --- a/ChattoApp/ChattoApp/Source/DemoChatViewController.swift +++ b/ChattoApp/ChattoApp/Source/DemoChatViewController.swift @@ -84,7 +84,7 @@ class DemoChatViewController: BaseChatViewController { ) ], SendingStatusModel.chatItemType: [SendingStatusPresenterBuilder()], - WeekDayDatestamp.chatItemType: [WeekDayDatestampPresenterBuilder()] + TimeSeparatorModel.chatItemType: [TimeSeparatorPresenterBuilder()] ] } diff --git a/ChattoApp/ChattoApp/Source/Time Separator/TimeSeparatorCollectionViewCell.swift b/ChattoApp/ChattoApp/Source/Time Separator/TimeSeparatorCollectionViewCell.swift new file mode 100644 index 000000000..3be897ca2 --- /dev/null +++ b/ChattoApp/ChattoApp/Source/Time Separator/TimeSeparatorCollectionViewCell.swift @@ -0,0 +1,68 @@ +/* + The MIT License (MIT) + + Copyright (c) 2015-present Badoo Trading Limited. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +import Foundation +import UIKit +import Chatto + +class TimeSeparatorCollectionViewCell: UICollectionViewCell { + + private let label: UILabel = UILabel() + + override init(frame: CGRect) { + super.init(frame: frame) + self.commonInit() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + self.commonInit() + } + + private func commonInit() { + self.label.font = UIFont.systemFontOfSize(12) + self.label.textAlignment = .Center + self.label.textColor = UIColor.grayColor() + self.contentView.addSubview(label) + } + + var text: String = "" { + didSet { + if oldValue != text { + self.setTextOnLabel(text) + } + } + } + + private func setTextOnLabel(text: String) { + self.label.text = text + self.setNeedsLayout() + } + + override func layoutSubviews() { + super.layoutSubviews() + self.label.bounds.size = self.label.sizeThatFits(self.contentView.bounds.size) + self.label.center = self.contentView.center + } +} diff --git a/ChattoApp/ChattoApp/Source/Time Separator/TimeSeparatorModel.swift b/ChattoApp/ChattoApp/Source/Time Separator/TimeSeparatorModel.swift new file mode 100644 index 000000000..9e973bcec --- /dev/null +++ b/ChattoApp/ChattoApp/Source/Time Separator/TimeSeparatorModel.swift @@ -0,0 +1,56 @@ +/* + The MIT License (MIT) + + Copyright (c) 2015-present Badoo Trading Limited. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +import Foundation +import UIKit +import Chatto + +class TimeSeparatorModel: ChatItemProtocol { + let uid: String + let type: String = TimeSeparatorModel.chatItemType + let date: String + + static var chatItemType: ChatItemType { + return "TimeSeparatorModel" + } + + init(uid: String, date: String) { + self.date = date + self.uid = uid + } +} + +extension NSDate { + // Have a time stamp formatter to avoid keep creating new ones. This improves performance + private static let weekdayAndDateStampDateFormatter: NSDateFormatter = { + let dateFormatter = NSDateFormatter() + dateFormatter.timeZone = NSTimeZone.localTimeZone() + dateFormatter.dateFormat = "EEEE, MMM dd yyyy" // "Monday, Mar 7 2016" + return dateFormatter + }() + + func toWeekDayAndDateString() -> String { + return NSDate.weekdayAndDateStampDateFormatter.stringFromDate(self) + } +} diff --git a/ChattoApp/ChattoApp/Source/Time Separator/TimeSeparatorPresenter.swift b/ChattoApp/ChattoApp/Source/Time Separator/TimeSeparatorPresenter.swift new file mode 100644 index 000000000..be325d53d --- /dev/null +++ b/ChattoApp/ChattoApp/Source/Time Separator/TimeSeparatorPresenter.swift @@ -0,0 +1,78 @@ +/* + The MIT License (MIT) + + Copyright (c) 2015-present Badoo Trading Limited. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +import Foundation +import UIKit +import Chatto + +public class TimeSeparatorPresenterBuilder: ChatItemPresenterBuilderProtocol { + + public func canHandleChatItem(chatItem: ChatItemProtocol) -> Bool { + return chatItem is TimeSeparatorModel + } + + public func createPresenterWithChatItem(chatItem: ChatItemProtocol) -> ChatItemPresenterProtocol { + assert(self.canHandleChatItem(chatItem)) + return TimeSeparatorPresenter(timeSeparatorModel: chatItem as! TimeSeparatorModel) + } + + public var presenterType: ChatItemPresenterProtocol.Type { + return TimeSeparatorPresenter.self + } +} + +class TimeSeparatorPresenter: ChatItemPresenterProtocol { + + let timeSeparatorModel: TimeSeparatorModel + init (timeSeparatorModel: TimeSeparatorModel) { + self.timeSeparatorModel = timeSeparatorModel + } + + private static let cellReuseIdentifier = TimeSeparatorCollectionViewCell.self.description() + + static func registerCells(collectionView: UICollectionView) { + collectionView.registerClass(TimeSeparatorCollectionViewCell.self, forCellWithReuseIdentifier: cellReuseIdentifier) + } + + func dequeueCell(collectionView collectionView: UICollectionView, indexPath: NSIndexPath) -> UICollectionViewCell { + return collectionView.dequeueReusableCellWithReuseIdentifier(TimeSeparatorPresenter.cellReuseIdentifier, forIndexPath: indexPath) + } + + func configureCell(cell: UICollectionViewCell, decorationAttributes: ChatItemDecorationAttributesProtocol?) { + guard let timeSeparatorCell = cell as? TimeSeparatorCollectionViewCell else { + assert(false, "expecting status cell") + return + } + + timeSeparatorCell.text = self.timeSeparatorModel.date + } + + var canCalculateHeightInBackground: Bool { + return true + } + + func heightForCell(maximumWidth width: CGFloat, decorationAttributes: ChatItemDecorationAttributesProtocol?) -> CGFloat { + return 24 + } +} diff --git a/ChattoApp/ChattoApp/Source/TimestampSeparatorView.swift b/ChattoApp/ChattoApp/Source/TimestampSeparatorView.swift deleted file mode 100644 index de86e9968..000000000 --- a/ChattoApp/ChattoApp/Source/TimestampSeparatorView.swift +++ /dev/null @@ -1,148 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016-present Zhao Wang. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -import Foundation -import UIKit -import Chatto - -extension NSDate { - // Have a time stamp formatter to avoid keep creating new ones. This improves performance - private static let weekdayAndDateStampDateFormatter: NSDateFormatter = { - let dateFormatter = NSDateFormatter() - dateFormatter.timeZone = NSTimeZone.localTimeZone() - dateFormatter.dateFormat = "EEEE, MMM dd yyyy" // "Monday, Mar 7 2016" - return dateFormatter - }() - - func toWeekDayAndDateString() -> String { - return NSDate.weekdayAndDateStampDateFormatter.stringFromDate(self) - } -} - -class WeekDayDatestamp: ChatItemProtocol { - let uid: String - let type: String = WeekDayDatestamp.chatItemType - - static var chatItemType: ChatItemType { - return "WeekDayDatestamp" - } - - init(date: NSDate) { - let datestampString = date.toWeekDayAndDateString() - self.uid = datestampString.uppercaseString - } -} - -class WeekDayDatestampCollectionViewCell: UICollectionViewCell { - private let label: UILabel = UILabel() - - override init(frame: CGRect) { - super.init(frame: frame) - commonInit() - } - - required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - commonInit() - } - - private func commonInit() { - label.font = UIFont.systemFontOfSize(12) - label.textAlignment = .Center - label.textColor = UIColor.grayColor() - - self.contentView.addSubview(label) - } - - var text: String = "" { - didSet { - if oldValue != text { - setTextOnLabel(text) - } - } - } - - private func setTextOnLabel(text: String) { - label.text = text - label.sizeToFit() - setNeedsLayout() - } - - override func layoutSubviews() { - super.layoutSubviews() - label.center = self.contentView.center - } -} - -public class WeekDayDatestampPresenterBuilder: ChatItemPresenterBuilderProtocol { - - public func canHandleChatItem(chatItem: ChatItemProtocol) -> Bool { - return chatItem is WeekDayDatestamp - } - - public func createPresenterWithChatItem(chatItem: ChatItemProtocol) -> ChatItemPresenterProtocol { - assert(self.canHandleChatItem(chatItem)) - return WeekDayDatestampPresenter(weekDayDatestamp: chatItem as! WeekDayDatestamp) - } - - public var presenterType: ChatItemPresenterProtocol.Type { - return WeekDayDatestampPresenter.self - } -} - -class WeekDayDatestampPresenter: ChatItemPresenterProtocol { - - let weekDayDatestamp: WeekDayDatestamp - init (weekDayDatestamp: WeekDayDatestamp) { - self.weekDayDatestamp = weekDayDatestamp - } - - private static let cellReuseIdentifier = WeekDayDatestampCollectionViewCell.self.description() - - static func registerCells(collectionView: UICollectionView) { - collectionView.registerClass(WeekDayDatestampCollectionViewCell.self, forCellWithReuseIdentifier: cellReuseIdentifier) - } - - func dequeueCell(collectionView collectionView: UICollectionView, indexPath: NSIndexPath) -> UICollectionViewCell { - let cell = collectionView.dequeueReusableCellWithReuseIdentifier(WeekDayDatestampPresenter.cellReuseIdentifier, forIndexPath: indexPath) - return cell - } - - func configureCell(cell: UICollectionViewCell, decorationAttributes: ChatItemDecorationAttributesProtocol?) { - guard let datestamp = cell as? WeekDayDatestampCollectionViewCell else { - assert(false, "expecting status cell") - return - } - - datestamp.text = weekDayDatestamp.uid - } - - var canCalculateHeightInBackground: Bool { - return true - } - - func heightForCell(maximumWidth width: CGFloat, decorationAttributes: ChatItemDecorationAttributesProtocol?) -> CGFloat { - return 24 - } -}