Skip to content

Commit

Permalink
Merge pull request badoo#1 from badoo/chatto-inception
Browse files Browse the repository at this point in the history
Chatto inception
  • Loading branch information
diegosanchezr committed Nov 27, 2015
2 parents ab5b944 + 2884160 commit ea3dc6b
Show file tree
Hide file tree
Showing 244 changed files with 15,967 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
language: objective-c
osx_image: xcode7.1

script:
- xcodebuild clean build test -project ./Chatto/Chatto.xcodeproj -scheme Chatto -sdk iphonesimulator -configuration Debug | xcpretty; (curl -s https://codecov.io/bash) | bash
- rm -rf ~/Library/Developer/Xcode/DerivedData
- xcodebuild clean build test -project ./ChattoAdditions/ChattoAdditions.xcodeproj -scheme ChattoAdditions -sdk iphonesimulator -configuration Debug | xcpretty; (curl -s https://codecov.io/bash) | bash
8 changes: 8 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Names should be added to this file like so:
# Name or Organization <email address>

Diego Sánchez <[email protected]>
Anton Schukin <[email protected]>

&yet LLC
Badoo
16 changes: 16 additions & 0 deletions Chatto.podspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Pod::Spec.new do |s|
s.name = "Chatto"
s.version = "1.0.0"
s.summary = "Chat framework in Swift"
s.description = <<-DESC
Lightweight chat framework to build Chat apps
DESC
s.homepage = "https://github.com/badoo/Chatto"
s.license = { :type => "MIT"}
s.platform = :ios, "8.0"
s.source = { :git => "https://github.com/badoo/Chatto.git", :tag => s.version.to_s }
s.source_files = "Chatto/Source/**/*.{h,m,swift}"
s.public_header_files = "Chatto/Source/**/*.h"
s.requires_arc = true
s.resources = ["Chatto/Source/**/*.xib", "Chatto/Source/**/*.storyboard", "Chatto/Source/**/*.xcassets"]
end
11 changes: 11 additions & 0 deletions Chatto/.swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
disabled_rules: # rule identifiers to exclude from running
- file_length
- force_cast
- function_body_length
- line_length
- todo
- type_body_length
- variable_name
included: # paths to include during linting. `--path` is ignored if present. takes precendence over `excluded`.
- Source
excluded: # paths to ignore during linting. overridden by `included`.
525 changes: 525 additions & 0 deletions Chatto/Chatto.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

100 changes: 100 additions & 0 deletions Chatto/Chatto.xcodeproj/xcshareddata/xcschemes/Chatto.xcscheme
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0720"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C32BB71F1BE0504D0069EC50"
BuildableName = "Chatto.framework"
BlueprintName = "Chatto"
ReferencedContainer = "container:Chatto.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C32BB7291BE0504D0069EC50"
BuildableName = "ChattoTests.xctest"
BlueprintName = "ChattoTests"
ReferencedContainer = "container:Chatto.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C32BB71F1BE0504D0069EC50"
BuildableName = "Chatto.framework"
BlueprintName = "Chatto"
ReferencedContainer = "container:Chatto.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C32BB71F1BE0504D0069EC50"
BuildableName = "Chatto.framework"
BlueprintName = "Chatto"
ReferencedContainer = "container:Chatto.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C32BB71F1BE0504D0069EC50"
BuildableName = "Chatto.framework"
BlueprintName = "Chatto"
ReferencedContainer = "container:Chatto.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
111 changes: 111 additions & 0 deletions Chatto/Source/Chat Items/BaseChatItemPresenter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
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 UIKit

public enum ChatItemVisibility {
case Hidden
case Appearing
case Visible
}

public class BaseChatItemPresenter<CellT: UICollectionViewCell>: ChatItemPresenterProtocol {
public final weak var cell: CellT?

public init() { }

public class func registerCells(collectionView: UICollectionView) {
assert(false, "Implement in subclass")
}

public var canCalculateHeightInBackground: Bool {
return false
}

public func heightForCell(maximumWidth width: CGFloat, decorationAttributes: ChatItemDecorationAttributesProtocol?) -> CGFloat {
assert(false, "Implement in subclass")
return 0
}

public func dequeueCell(collectionView collectionView: UICollectionView, indexPath: NSIndexPath) -> UICollectionViewCell {
assert(false, "Implemenent in subclass")
return UICollectionViewCell()
}

public func configureCell(cell: UICollectionViewCell, decorationAttributes: ChatItemDecorationAttributesProtocol?) {
assert(false, "Implemenent in subclass")
}

final public private(set) var itemVisibility: ChatItemVisibility = .Hidden

// Need to override default implementatios. Otherwise subclasses's code won't be executed
// http://stackoverflow.com/questions/31795158/swift-2-protocol-extension-not-calling-overriden-method-correctly
public final func cellWillBeShown(cell: UICollectionViewCell) {
if let cell = cell as? CellT {
self.cell = cell
self.itemVisibility = .Appearing
self.cellWillBeShown()
self.itemVisibility = .Visible
} else {
assert(false, "Invalid cell was given to presenter!")
}
}

public func cellWillBeShown() {
// Hook for subclasses
}

public func shouldShowMenu() -> Bool {
return false
}

public final func cellWasHidden(cell: UICollectionViewCell) {
// Carefull!! This doesn't mean that this is no longer visible
// If cell is replaced (due to a reload for instance) we can have the following sequence:
// - New cell is taken from the pool and configured. We'll get cellWillBeShown
// - Old cell is removed. We'll get cellWasHidden
// --> We need to check that this cell is the last one made visible
if let cell = cell as? CellT {
if cell === self.cell {
self.cell = nil
self.itemVisibility = .Hidden
self.cellWasHidden()
}
} else {
assert(false, "Invalid cell was given to presenter!")
}
}

public func cellWasHidden() {
// Hook for subclasses. Here we are not visible for real.
}

public func canPerformMenuControllerAction(action: Selector) -> Bool {
return false
}

public func performMenuControllerAction(action: Selector) {
assert(self.canPerformMenuControllerAction(action))
}
}
63 changes: 63 additions & 0 deletions Chatto/Source/Chat Items/ChatItemProtocolDefinitions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
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

public typealias ChatItemType = String

public protocol ChatItemProtocol: class, UniqueIdentificable {
var type: ChatItemType { get }
}

public protocol ChatItemDecorationAttributesProtocol {
var bottomMargin: CGFloat { get }
}

public protocol ChatItemPresenterProtocol: class {
static func registerCells(collectionView: UICollectionView)
var canCalculateHeightInBackground: Bool { get } // Default is false
func heightForCell(maximumWidth width: CGFloat, decorationAttributes: ChatItemDecorationAttributesProtocol?) -> CGFloat
func dequeueCell(collectionView collectionView: UICollectionView, indexPath: NSIndexPath) -> UICollectionViewCell
func configureCell(cell: UICollectionViewCell, decorationAttributes: ChatItemDecorationAttributesProtocol?)
func cellWillBeShown(cell: UICollectionViewCell) // optional
func cellWasHidden(cell: UICollectionViewCell) // optional
func shouldShowMenu() -> Bool // optional. Default is false
func canPerformMenuControllerAction(action: Selector) -> Bool // optional. Default is false
func performMenuControllerAction(action: Selector) // optional
}

public extension ChatItemPresenterProtocol { // Optionals
var canCalculateHeightInBackground: Bool { return false }
func cellWillBeShown(cell: UICollectionViewCell) {}
func cellWasHidden(cell: UICollectionViewCell) {}
func shouldShowMenu() -> Bool { return false }
func canPerformMenuControllerAction(action: Selector) -> Bool { return false }
func performMenuControllerAction(action: Selector) {}
}

public protocol ChatItemPresenterBuilderProtocol {
func canHandleChatItem(chatItem: ChatItemProtocol) -> Bool
func createPresenterWithChatItem(chatItem: ChatItemProtocol) -> ChatItemPresenterProtocol
var presenterType: ChatItemPresenterProtocol.Type { get }
}
52 changes: 52 additions & 0 deletions Chatto/Source/Chat Items/DummyChatItemPresenter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
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

// Handles messages that aren't supported so they appear as invisible
class DummyChatItemPresenter: ChatItemPresenterProtocol {

class func registerCells(collectionView: UICollectionView) {
collectionView.registerClass(DummyCollectionViewCell.self, forCellWithReuseIdentifier: "cell-id-unhandled-message")
}

var canCalculateHeightInBackground: Bool {
return true
}

func heightForCell(maximumWidth width: CGFloat, decorationAttributes: ChatItemDecorationAttributesProtocol?) -> CGFloat {
return 0
}

func dequeueCell(collectionView collectionView: UICollectionView, indexPath: NSIndexPath) -> UICollectionViewCell {
return collectionView.dequeueReusableCellWithReuseIdentifier("cell-id-unhandled-message", forIndexPath: indexPath)
}

func configureCell(cell: UICollectionViewCell, decorationAttributes: ChatItemDecorationAttributesProtocol?) {
cell.hidden = true
}
}


class DummyCollectionViewCell: UICollectionViewCell {}
Loading

0 comments on commit ea3dc6b

Please sign in to comment.