Compare commits

...

3 Commits

Author SHA1 Message Date
Jesse Squires
78b1797bc0 revert to 5.3.2 on this branch 2014-10-13 17:57:02 -07:00
Jesse Squires
dff04f82a9 update spec 2014-10-13 17:46:44 -07:00
Jesse Squires
825cddacf1 Revert "bump version nums"
This reverts commit 7198f760aa.

Conflicts:
	JSQMessagesDemo/Info.plist
	JSQMessagesViewController.podspec
2014-10-13 17:42:23 -07:00
216 changed files with 5017 additions and 6343 deletions

0
Assets/JSQmessages.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

0
Assets/jsq_message_chat_icon.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

0
Assets/jsq_messages_banner.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

0
Assets/jsq_messages_banner.psd Normal file → Executable file
View File

0
Assets/jsq_messages_icon.psd Normal file → Executable file
View File

0
Assets/jsq_messages_splash.psd Normal file → Executable file
View File

0
Assets/jsq_messages_splash_ipad.psd Normal file → Executable file
View File

0
CONTRIBUTING.md Normal file → Executable file
View File

4595
JSQMessages.xcodeproj/project.pbxproj Normal file → Executable file

File diff suppressed because it is too large Load Diff

0
JSQMessages.xcodeproj/project.xcworkspace/contents.xcworkspacedata generated Normal file → Executable file
View File

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
<false/>
</dict>
</plist>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0600"
LastUpgradeVersion = "0510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -14,7 +14,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4F6B28C25B7B1259BD8C5B8B"
BlueprintIdentifier = "26344A22808645D9967C8244"
BuildableName = "libPods.a"
BlueprintName = "Pods"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
@ -28,7 +28,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "88A25F0119D8DEC400924534"
BlueprintIdentifier = "885D592818CBD13D00D77BB3"
BuildableName = "JSQMessages.app"
BlueprintName = "JSQMessages"
ReferencedContainer = "container:JSQMessages.xcodeproj">
@ -42,7 +42,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "88A25F1A19D8DEC400924534"
BlueprintIdentifier = "885D594C18CBD13D00D77BB3"
BuildableName = "JSQMessagesTests.xctest"
BlueprintName = "JSQMessagesTests"
ReferencedContainer = "container:JSQMessages.xcodeproj">
@ -60,7 +60,7 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "88A25F1A19D8DEC400924534"
BlueprintIdentifier = "885D594C18CBD13D00D77BB3"
BuildableName = "JSQMessagesTests.xctest"
BlueprintName = "JSQMessagesTests"
ReferencedContainer = "container:JSQMessages.xcodeproj">
@ -70,7 +70,7 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "88A25F0119D8DEC400924534"
BlueprintIdentifier = "885D592818CBD13D00D77BB3"
BuildableName = "JSQMessages.app"
BlueprintName = "JSQMessages"
ReferencedContainer = "container:JSQMessages.xcodeproj">
@ -89,7 +89,7 @@
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "88A25F0119D8DEC400924534"
BlueprintIdentifier = "885D592818CBD13D00D77BB3"
BuildableName = "JSQMessages.app"
BlueprintName = "JSQMessages"
ReferencedContainer = "container:JSQMessages.xcodeproj">
@ -107,7 +107,7 @@
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "88A25F0119D8DEC400924534"
BlueprintIdentifier = "885D592818CBD13D00D77BB3"
BuildableName = "JSQMessages.app"
BlueprintName = "JSQMessages"
ReferencedContainer = "container:JSQMessages.xcodeproj">

11
JSQMessages.xcworkspace/contents.xcworkspacedata generated Normal file → Executable file
View File

@ -1,10 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:JSQMessages.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
<?xml version='1.0' encoding='UTF-8'?><Workspace version='1.0'><FileRef location='group:JSQMessages.xcodeproj'/><FileRef location='group:Pods/Pods.xcodeproj'/></Workspace>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
<false/>
</dict>
</plist>

257
JSQMessagesDemo/Base.lproj/Main.storyboard Normal file → Executable file
View File

@ -1,14 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6245" systemVersion="13F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="JRd-Be-psV">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="5053" systemVersion="13C64" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="JRd-Be-psV">
<dependencies>
<deployment defaultVersion="1792" identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6238"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3733"/>
</dependencies>
<scenes>
<!--Root View Controller-->
<!--Table View Controller - Root View Controller-->
<scene sceneID="IjL-71-Ll6">
<objects>
<tableViewController id="rXs-qR-ns2" customClass="TableViewController" sceneMemberID="viewController">
<tableViewController id="rXs-qR-ns2" customClass="JSQTableViewController" sceneMemberID="viewController">
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" id="d0b-Sx-5kJ">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@ -37,252 +36,12 @@
<connections>
<segue destination="JdJ-0X-ZL8" kind="push" identifier="seguePushDemoVC" id="Hvf-k8-GSP"/>
<segue destination="s4z-xn-r6C" kind="modal" identifier="segueModalDemoVC" id="4UP-0e-ylo"/>
<segue destination="y7K-ZU-Xs9" kind="push" identifier="SegueToSettings" id="u7b-st-FND"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="IcC-ug-dCB" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-2982" y="274"/>
</scene>
<!--Settings-->
<scene sceneID="6rZ-ao-qyI">
<objects>
<tableViewController id="y7K-ZU-Xs9" customClass="DemoSettingsViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" allowsSelection="NO" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" id="GY5-ob-knb">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<sections>
<tableViewSection headerTitle="Messages" id="ygb-Dp-o4r">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="Eii-ro-1yZ">
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Eii-ro-1yZ" id="qU9-o3-MWC">
<autoresizingMask key="autoresizingMask"/>
<subviews>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="K7N-os-fuc">
<rect key="frame" x="263" y="6" width="51" height="31"/>
<constraints>
<constraint firstAttribute="width" constant="49" id="A6s-Sr-u8U"/>
<constraint firstAttribute="height" constant="31" id="z9i-uJ-MBq"/>
</constraints>
<connections>
<action selector="didTapSwitch:" destination="y7K-ZU-Xs9" eventType="valueChanged" id="Ebi-bs-7Bc"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Load extra messages" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bSS-CD-nfD">
<rect key="frame" x="8" y="10" width="247" height="24"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="bSS-CD-nfD" firstAttribute="top" secondItem="qU9-o3-MWC" secondAttribute="top" constant="10" id="4Iw-W0-qZs"/>
<constraint firstAttribute="trailing" secondItem="K7N-os-fuc" secondAttribute="trailing" constant="8" id="Fex-nr-C1R"/>
<constraint firstAttribute="bottom" secondItem="K7N-os-fuc" secondAttribute="bottom" constant="6" id="IBG-gn-Fpk"/>
<constraint firstItem="bSS-CD-nfD" firstAttribute="leading" secondItem="qU9-o3-MWC" secondAttribute="leading" constant="8" id="N5B-E5-Pzk"/>
<constraint firstItem="K7N-os-fuc" firstAttribute="leading" secondItem="bSS-CD-nfD" secondAttribute="trailing" constant="8" id="O2Y-G9-d6n"/>
<constraint firstItem="K7N-os-fuc" firstAttribute="top" secondItem="qU9-o3-MWC" secondAttribute="top" constant="6" id="UbM-aE-caS"/>
<constraint firstAttribute="bottom" secondItem="bSS-CD-nfD" secondAttribute="bottom" constant="9" id="poL-wE-Eir"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="bZI-G1-eYA">
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="bZI-G1-eYA" id="1Ho-Zz-KN0">
<autoresizingMask key="autoresizingMask"/>
<subviews>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hMq-Ee-EJK">
<rect key="frame" x="263" y="6" width="51" height="31"/>
<constraints>
<constraint firstAttribute="height" constant="31" id="gM4-dK-cl7"/>
<constraint firstAttribute="width" constant="49" id="hvu-Yy-NTG"/>
</constraints>
<connections>
<action selector="didTapSwitch:" destination="y7K-ZU-Xs9" eventType="valueChanged" id="JCb-EJ-M9U"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Load really long message" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YV3-GH-Yul">
<rect key="frame" x="8" y="10" width="247" height="24"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="hMq-Ee-EJK" firstAttribute="leading" secondItem="YV3-GH-Yul" secondAttribute="trailing" constant="8" id="KFO-nO-4r4"/>
<constraint firstItem="YV3-GH-Yul" firstAttribute="top" secondItem="1Ho-Zz-KN0" secondAttribute="top" constant="10" id="Lgl-fY-a8c"/>
<constraint firstAttribute="bottom" secondItem="YV3-GH-Yul" secondAttribute="bottom" constant="9" id="NvL-b8-QDl"/>
<constraint firstAttribute="bottom" secondItem="hMq-Ee-EJK" secondAttribute="bottom" constant="6" id="aef-Rh-49d"/>
<constraint firstItem="hMq-Ee-EJK" firstAttribute="top" secondItem="1Ho-Zz-KN0" secondAttribute="top" constant="6" id="csX-us-yCd"/>
<constraint firstAttribute="trailing" secondItem="hMq-Ee-EJK" secondAttribute="trailing" constant="8" id="xDE-tf-5mB"/>
<constraint firstItem="YV3-GH-Yul" firstAttribute="leading" secondItem="1Ho-Zz-KN0" secondAttribute="leading" constant="8" id="xyR-oc-iUp"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="2Th-gL-oAN">
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="2Th-gL-oAN" id="OFq-Mz-mbl">
<autoresizingMask key="autoresizingMask"/>
<subviews>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="baL-Tb-bTJ">
<rect key="frame" x="263" y="6" width="51" height="31"/>
<constraints>
<constraint firstAttribute="width" constant="49" id="SaV-RG-DVL"/>
<constraint firstAttribute="height" constant="31" id="dXb-pb-etA"/>
</constraints>
<connections>
<action selector="didTapSwitch:" destination="y7K-ZU-Xs9" eventType="valueChanged" id="w1H-5W-oip"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Empty view, no messages" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DoU-SU-Nek">
<rect key="frame" x="8" y="10" width="247" height="24"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="DoU-SU-Nek" firstAttribute="leading" secondItem="OFq-Mz-mbl" secondAttribute="leading" constant="8" id="A9k-hI-0BH"/>
<constraint firstAttribute="bottom" secondItem="baL-Tb-bTJ" secondAttribute="bottom" constant="6" id="Ff7-1T-EbZ"/>
<constraint firstItem="DoU-SU-Nek" firstAttribute="top" secondItem="OFq-Mz-mbl" secondAttribute="top" constant="10" id="Uji-LE-8IA"/>
<constraint firstAttribute="trailing" secondItem="baL-Tb-bTJ" secondAttribute="trailing" constant="8" id="dUp-7b-g3p"/>
<constraint firstItem="baL-Tb-bTJ" firstAttribute="leading" secondItem="DoU-SU-Nek" secondAttribute="trailing" constant="8" id="fxZ-zy-ksL"/>
<constraint firstAttribute="bottom" secondItem="DoU-SU-Nek" secondAttribute="bottom" constant="9" id="h0B-EX-3MW"/>
<constraint firstItem="baL-Tb-bTJ" firstAttribute="top" secondItem="OFq-Mz-mbl" secondAttribute="top" constant="6" id="v5e-xk-srk"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Avatars" id="ns0-OO-PGu">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="hYS-4f-iL6">
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hYS-4f-iL6" id="dk1-tc-gux">
<autoresizingMask key="autoresizingMask"/>
<subviews>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fLZ-NC-aPO">
<rect key="frame" x="263" y="6" width="51" height="31"/>
<constraints>
<constraint firstAttribute="width" constant="49" id="1lf-6y-hgz"/>
<constraint firstAttribute="height" constant="31" id="rdQ-ol-d20"/>
</constraints>
<connections>
<action selector="didTapSwitch:" destination="y7K-ZU-Xs9" eventType="valueChanged" id="WnT-b7-og6"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Incoming avatars" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="RUq-Pa-3nx">
<rect key="frame" x="8" y="10" width="247" height="24"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="RUq-Pa-3nx" secondAttribute="bottom" constant="9" id="7Yt-uN-sOS"/>
<constraint firstItem="RUq-Pa-3nx" firstAttribute="top" secondItem="dk1-tc-gux" secondAttribute="top" constant="10" id="Aih-Lc-tq7"/>
<constraint firstItem="fLZ-NC-aPO" firstAttribute="leading" secondItem="RUq-Pa-3nx" secondAttribute="trailing" constant="8" id="Cfo-7m-Vyd"/>
<constraint firstAttribute="trailing" secondItem="fLZ-NC-aPO" secondAttribute="trailing" constant="8" id="Mgz-VG-tDn"/>
<constraint firstItem="fLZ-NC-aPO" firstAttribute="top" secondItem="dk1-tc-gux" secondAttribute="top" constant="6" id="S6i-he-vB9"/>
<constraint firstItem="RUq-Pa-3nx" firstAttribute="leading" secondItem="dk1-tc-gux" secondAttribute="leading" constant="8" id="mhd-oX-p53"/>
<constraint firstAttribute="bottom" secondItem="fLZ-NC-aPO" secondAttribute="bottom" constant="6" id="yyq-Sg-nJi"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="VF7-uo-6Pc">
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="VF7-uo-6Pc" id="zad-JQ-TRI">
<autoresizingMask key="autoresizingMask"/>
<subviews>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LuM-mk-Zj6">
<rect key="frame" x="263" y="6" width="51" height="31"/>
<constraints>
<constraint firstAttribute="height" constant="31" id="QXv-ty-g0B"/>
<constraint firstAttribute="width" constant="49" id="rZ3-cO-f8t"/>
</constraints>
<connections>
<action selector="didTapSwitch:" destination="y7K-ZU-Xs9" eventType="valueChanged" id="rNB-Bx-Uh3"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Outgoing avatars" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9Rr-S8-Uae">
<rect key="frame" x="8" y="10" width="247" height="24"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="LuM-mk-Zj6" secondAttribute="bottom" constant="6" id="1G7-8S-rYC"/>
<constraint firstAttribute="bottom" secondItem="9Rr-S8-Uae" secondAttribute="bottom" constant="9" id="5xp-ez-tac"/>
<constraint firstItem="LuM-mk-Zj6" firstAttribute="leading" secondItem="9Rr-S8-Uae" secondAttribute="trailing" constant="8" id="C5c-2A-mli"/>
<constraint firstAttribute="trailing" secondItem="LuM-mk-Zj6" secondAttribute="trailing" constant="8" id="Lep-LY-D1h"/>
<constraint firstItem="LuM-mk-Zj6" firstAttribute="top" secondItem="zad-JQ-TRI" secondAttribute="top" constant="6" id="Y6a-JS-aLj"/>
<constraint firstItem="9Rr-S8-Uae" firstAttribute="leading" secondItem="zad-JQ-TRI" secondAttribute="leading" constant="8" id="Yao-VR-Is6"/>
<constraint firstItem="9Rr-S8-Uae" firstAttribute="top" secondItem="zad-JQ-TRI" secondAttribute="top" constant="10" id="Yiv-t6-Xj5"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Dynamic Behaviors" footerTitle="NOTE: This feature is experimental" id="o5m-OT-1Iw">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="q07-lZ-YdI">
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="q07-lZ-YdI" id="btE-Mk-fSE">
<autoresizingMask key="autoresizingMask"/>
<subviews>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uXC-2j-cgi">
<rect key="frame" x="263" y="6" width="51" height="31"/>
<constraints>
<constraint firstAttribute="height" constant="31" id="5bI-xQ-njj"/>
<constraint firstAttribute="width" constant="49" id="PG2-X2-FdD"/>
</constraints>
<connections>
<action selector="didTapSwitch:" destination="y7K-ZU-Xs9" eventType="valueChanged" id="oHB-iq-JSz"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Springy bubbles" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3d2-fZ-dx9">
<rect key="frame" x="8" y="10" width="247" height="24"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="3d2-fZ-dx9" firstAttribute="leading" secondItem="btE-Mk-fSE" secondAttribute="leading" constant="8" id="6Cs-6l-Xzp"/>
<constraint firstItem="uXC-2j-cgi" firstAttribute="leading" secondItem="3d2-fZ-dx9" secondAttribute="trailing" constant="8" id="7Mq-HR-4nY"/>
<constraint firstItem="uXC-2j-cgi" firstAttribute="top" secondItem="btE-Mk-fSE" secondAttribute="top" constant="6" id="Ajq-5g-XKo"/>
<constraint firstAttribute="bottom" secondItem="3d2-fZ-dx9" secondAttribute="bottom" constant="9" id="EzH-aB-ePQ"/>
<constraint firstAttribute="bottom" secondItem="uXC-2j-cgi" secondAttribute="bottom" constant="6" id="RCb-Mi-FHX"/>
<constraint firstItem="3d2-fZ-dx9" firstAttribute="top" secondItem="btE-Mk-fSE" secondAttribute="top" constant="10" id="btF-q4-HJg"/>
<constraint firstAttribute="trailing" secondItem="uXC-2j-cgi" secondAttribute="trailing" constant="8" id="zzu-aP-ZiL"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
<connections>
<outlet property="dataSource" destination="y7K-ZU-Xs9" id="4gP-Ip-VMs"/>
<outlet property="delegate" destination="y7K-ZU-Xs9" id="RdT-hW-mFp"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Settings" id="hrw-Dp-Tor"/>
<connections>
<outlet property="emptySwitch" destination="baL-Tb-bTJ" id="qk7-dH-53U"/>
<outlet property="extraMessagesSwitch" destination="K7N-os-fuc" id="qlF-0W-3JO"/>
<outlet property="incomingAvatarsSwitch" destination="fLZ-NC-aPO" id="0ck-t9-Hwt"/>
<outlet property="longMessageSwitch" destination="hMq-Ee-EJK" id="Vs2-fX-Hys"/>
<outlet property="outgoingAvatarsSwitch" destination="LuM-mk-Zj6" id="EAh-35-xjI"/>
<outlet property="springySwitch" destination="uXC-2j-cgi" id="Jzx-1y-VZP"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="5u5-k6-W2j" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-2982" y="1039"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="eGf-GM-ORQ">
<objects>
@ -298,10 +57,10 @@
</objects>
<point key="canvasLocation" x="-2409" y="619"/>
</scene>
<!--Demo Messages View Controller-->
<!--Demo View Controller-->
<scene sceneID="gOX-cv-CuN">
<objects>
<viewController storyboardIdentifier="DemoVC" id="JdJ-0X-ZL8" customClass="DemoMessagesViewController" sceneMemberID="viewController">
<viewController storyboardIdentifier="DemoVC" id="JdJ-0X-ZL8" customClass="JSQDemoViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="TE8-r2-pE8"/>
<viewControllerLayoutGuide type="bottom" id="H2n-HB-Ssl"/>
@ -332,10 +91,10 @@
</objects>
<point key="canvasLocation" x="-3413" y="274"/>
</scene>
<!--Demo Messages View Controller-->
<!--Demo View Controller-->
<scene sceneID="Rr5-W8-Xyh">
<objects>
<viewController id="2Qx-iu-03V" customClass="DemoMessagesViewController" sceneMemberID="viewController">
<viewController id="2Qx-iu-03V" customClass="JSQDemoViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="hTc-sT-can"/>
<viewControllerLayoutGuide type="bottom" id="BPF-eU-3uQ"/>

View File

@ -1,557 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// Documentation
// http://cocoadocs.org/docsets/JSQMessagesViewController
//
//
// GitHub
// https://github.com/jessesquires/JSQMessagesViewController
//
//
// License
// Copyright (c) 2014 Jesse Squires
// Released under an MIT license: http://opensource.org/licenses/MIT
//
#import "DemoMessagesViewController.h"
@implementation DemoMessagesViewController
#pragma mark - View lifecycle
/**
* Override point for customization.
*
* Customize your view.
* Look at the properties on `JSQMessagesViewController` and `JSQMessagesCollectionView` to see what is possible.
*
* Customize your layout.
* Look at the properties on `JSQMessagesCollectionViewFlowLayout` to see what is possible.
*/
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = @"JSQMessages";
/**
* You MUST set your senderId and display name
*/
self.senderId = kJSQDemoAvatarIdSquires;
self.senderDisplayName = kJSQDemoAvatarDisplayNameSquires;
/**
* Load up our fake data for the demo
*/
self.demoData = [[DemoModelData alloc] init];
/**
* You can set custom avatar sizes
*/
if (![NSUserDefaults incomingAvatarSetting]) {
self.collectionView.collectionViewLayout.incomingAvatarViewSize = CGSizeZero;
}
if (![NSUserDefaults outgoingAvatarSetting]) {
self.collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero;
}
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"typing"]
style:UIBarButtonItemStyleBordered
target:self
action:@selector(receiveMessagePressed:)];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.delegateModal) {
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop
target:self
action:@selector(closePressed:)];
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
/**
* Enable/disable springy bubbles, default is NO.
* You must set this from `viewDidAppear:`
* Note: this feature is mostly stable, but still experimental
*/
self.collectionView.collectionViewLayout.springinessEnabled = [NSUserDefaults springinessSetting];
}
#pragma mark - Actions
- (void)receiveMessagePressed:(UIBarButtonItem *)sender
{
/**
* DEMO ONLY
*
* The following is simply to simulate received messages for the demo.
* Do not actually do this.
*/
/**
* Show the typing indicator to be shown
*/
self.showTypingIndicator = !self.showTypingIndicator;
/**
* Scroll to actually view the indicator
*/
[self scrollToBottomAnimated:YES];
/**
* Copy last sent message, this will be the new "received" message
*/
JSQMessage *copyMessage = [[self.demoData.messages lastObject] copy];
if (!copyMessage) {
copyMessage = [JSQTextMessage messageWithSenderId:kJSQDemoAvatarIdJobs
displayName:kJSQDemoAvatarDisplayNameJobs
text:@"First received!"];
}
/**
* Allow typing indicator to show
*/
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSMutableArray *userIds = [[self.demoData.users allKeys] mutableCopy];
[userIds removeObject:self.senderId];
NSString *randomUserId = userIds[arc4random_uniform((int)[userIds count])];
JSQMessage *newMessage = nil;
id<JSQMessageMediaData> newMediaData = nil;
id newMediaAttachmentCopy = nil;
if ([copyMessage isKindOfClass:[JSQMediaMessage class]]) {
/**
* Last message was a media message
*/
id<JSQMessageMediaData> copyMediaData = copyMessage.media;
if ([copyMediaData isKindOfClass:[JSQPhotoMediaItem class]]) {
JSQPhotoMediaItem *photoItemCopy = [((JSQPhotoMediaItem *)copyMediaData) copy];
newMediaAttachmentCopy = [UIImage imageWithCGImage:photoItemCopy.image.CGImage];
/**
* Set image to nil to simulate "downloading" the image
* and show the placeholder view
*/
photoItemCopy.image = nil;
newMediaData = photoItemCopy;
}
else if ([copyMediaData isKindOfClass:[JSQLocationMediaItem class]]) {
JSQLocationMediaItem *locationItemCopy = [((JSQLocationMediaItem *)copyMediaData) copy];
newMediaAttachmentCopy = [locationItemCopy.location copy];
/**
* Set location to nil to simulate "downloading" the location data
*/
locationItemCopy.location = nil;
newMediaData = locationItemCopy;
}
else if ([copyMediaData isKindOfClass:[JSQVideoMediaitem class]]) {
JSQVideoMediaitem *videoItemCopy = [((JSQVideoMediaitem *)copyMediaData) copy];
newMediaAttachmentCopy = [videoItemCopy.fileURL copy];
/**
* Reset video item to simulate "downloading" the video
*/
videoItemCopy.fileURL = nil;
videoItemCopy.isReadyToPlay = NO;
newMediaData = videoItemCopy;
}
else {
NSLog(@"%s error: unrecognized media item", __PRETTY_FUNCTION__);
}
newMessage = [JSQMediaMessage messageWithSenderId:randomUserId
displayName:self.demoData.users[randomUserId]
media:newMediaData];
}
else {
/**
* Last message was a text message
*/
newMessage = [JSQTextMessage messageWithSenderId:randomUserId
displayName:self.demoData.users[randomUserId]
text:copyMessage.text];
}
/**
* Upon receiving a message, you should:
*
* 1. Play sound (optional)
* 2. Add new id<JSQMessageData> object to your data source
* 3. Call `finishReceivingMessage`
*/
[JSQSystemSoundPlayer jsq_playMessageReceivedSound];
[self.demoData.messages addObject:newMessage];
[self finishReceivingMessage];
if ([newMessage isKindOfClass:[JSQMediaMessage class]]) {
/**
* Simulate "downloading" media
*/
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
/**
* Media is "finished downloading", re-display visible cells
*
* If media cell is not visible, the next time it is dequeued the view controller will display its new attachment data
*
* Reload the specific item, or simply call `reloadData`
*/
if ([newMediaData isKindOfClass:[JSQPhotoMediaItem class]]) {
((JSQPhotoMediaItem *)newMediaData).image = newMediaAttachmentCopy;
[self.collectionView reloadData];
}
else if ([newMediaData isKindOfClass:[JSQLocationMediaItem class]]) {
[((JSQLocationMediaItem *)newMediaData)setLocation:newMediaAttachmentCopy withCompletionHandler:^{
[self.collectionView reloadData];
}];
}
else if ([newMediaData isKindOfClass:[JSQVideoMediaitem class]]) {
((JSQVideoMediaitem *)newMediaData).fileURL = newMediaAttachmentCopy;
((JSQVideoMediaitem *)newMediaData).isReadyToPlay = YES;
[self.collectionView reloadData];
}
else {
NSLog(@"%s error: unrecognized media item", __PRETTY_FUNCTION__);
}
});
}
});
}
- (void)closePressed:(UIBarButtonItem *)sender
{
[self.delegateModal didDismissJSQDemoViewController:self];
}
#pragma mark - JSQMessagesViewController method overrides
- (void)didPressSendButton:(UIButton *)button
withMessageText:(NSString *)text
senderId:(NSString *)senderId
senderDisplayName:(NSString *)senderDisplayName
date:(NSDate *)date
{
/**
* Sending a message. Your implementation of this method should do *at least* the following:
*
* 1. Play sound (optional)
* 2. Add new id<JSQMessageData> object to your data source
* 3. Call `finishSendingMessage`
*/
[JSQSystemSoundPlayer jsq_playMessageSentSound];
JSQTextMessage *message = [[JSQTextMessage alloc] initWithSenderId:senderId
senderDisplayName:senderDisplayName
date:date
text:text];
[self.demoData.messages addObject:message];
[self finishSendingMessage];
}
- (void)didPressAccessoryButton:(UIButton *)sender
{
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"Media messages"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@"Send photo", @"Send location", @"Send video", nil];
[sheet showFromToolbar:self.inputToolbar];
}
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == actionSheet.cancelButtonIndex) {
return;
}
switch (buttonIndex) {
case 0:
[self.demoData addPhotoMediaMessage];
break;
case 1:
{
__weak UICollectionView *weakView = self.collectionView;
[self.demoData addLocationMediaMessageCompletion:^{
[weakView reloadData];
}];
}
break;
case 2:
[self.demoData addVideoMediaMessage];
break;
}
[JSQSystemSoundPlayer jsq_playMessageSentSound];
[self finishSendingMessage];
}
#pragma mark - JSQMessages CollectionView DataSource
- (id<JSQMessageData>)collectionView:(JSQMessagesCollectionView *)collectionView messageDataForItemAtIndexPath:(NSIndexPath *)indexPath
{
return [self.demoData.messages objectAtIndex:indexPath.item];
}
- (id<JSQMessageBubbleImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView messageBubbleImageDataForItemAtIndexPath:(NSIndexPath *)indexPath
{
/**
* You may return nil here if you do not want bubbles.
* In this case, you should set the background color of your collection view cell's textView.
*
* Otherwise, return your previously created bubble image data objects.
*/
JSQMessage *message = [self.demoData.messages objectAtIndex:indexPath.item];
if ([message.senderId isEqualToString:self.senderId]) {
return self.demoData.outgoingBubbleImageData;
}
return self.demoData.incomingBubbleImageData;
}
- (id<JSQMessageAvatarImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView avatarImageDataForItemAtIndexPath:(NSIndexPath *)indexPath
{
/**
* Return `nil` here if you do not want avatars.
* If you do return `nil`, be sure to do the following in `viewDidLoad`:
*
* self.collectionView.collectionViewLayout.incomingAvatarViewSize = CGSizeZero;
* self.collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero;
*
* It is possible to have only outgoing avatars or only incoming avatars, too.
*/
/**
* Return your previously created avatar image data objects.
*
* Note: these the avatars will be sized according to these values:
*
* self.collectionView.collectionViewLayout.incomingAvatarViewSize
* self.collectionView.collectionViewLayout.outgoingAvatarViewSize
*
* Override the defaults in `viewDidLoad`
*/
JSQMessage *message = [self.demoData.messages objectAtIndex:indexPath.item];
if ([message.senderId isEqualToString:self.senderId]) {
if (![NSUserDefaults outgoingAvatarSetting]) {
return nil;
}
}
else {
if (![NSUserDefaults incomingAvatarSetting]) {
return nil;
}
}
return [self.demoData.avatars objectForKey:message.senderId];
}
- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath
{
/**
* This logic should be consistent with what you return from `heightForCellTopLabelAtIndexPath:`
* The other label text delegate methods should follow a similar pattern.
*
* Show a timestamp for every 3rd message
*/
if (indexPath.item % 3 == 0) {
JSQMessage *message = [self.demoData.messages objectAtIndex:indexPath.item];
return [[JSQMessagesTimestampFormatter sharedFormatter] attributedTimestampForDate:message.date];
}
return nil;
}
- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForMessageBubbleTopLabelAtIndexPath:(NSIndexPath *)indexPath
{
JSQMessage *message = [self.demoData.messages objectAtIndex:indexPath.item];
/**
* iOS7-style sender name labels
*/
if ([message.senderId isEqualToString:self.senderId]) {
return nil;
}
if (indexPath.item - 1 > 0) {
JSQMessage *previousMessage = [self.demoData.messages objectAtIndex:indexPath.item - 1];
if ([[previousMessage senderId] isEqualToString:message.senderId]) {
return nil;
}
}
/**
* Don't specify attributes to use the defaults.
*/
return [[NSAttributedString alloc] initWithString:message.senderDisplayName];
}
- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath
{
return nil;
}
#pragma mark - UICollectionView DataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [self.demoData.messages count];
}
- (UICollectionViewCell *)collectionView:(JSQMessagesCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
/**
* Override point for customizing cells
*/
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
/**
* Configure almost *anything* on the cell
*
* Text colors, label text, label colors, etc.
*
*
* DO NOT set `cell.textView.font` !
* Instead, you need to set `self.collectionView.collectionViewLayout.messageBubbleFont` to the font you want in `viewDidLoad`
*
*
* DO NOT manipulate cell layout information!
* Instead, override the properties you want on `self.collectionView.collectionViewLayout` from `viewDidLoad`
*/
JSQMessage *msg = [self.demoData.messages objectAtIndex:indexPath.item];
if ([msg isKindOfClass:[JSQTextMessage class]]) {
if ([msg.senderId isEqualToString:self.senderId]) {
cell.textView.textColor = [UIColor blackColor];
}
else {
cell.textView.textColor = [UIColor whiteColor];
}
cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor,
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };
}
return cell;
}
#pragma mark - JSQMessages collection view flow layout delegate
#pragma mark - Adjusting cell label heights
- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView
layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath
{
/**
* Each label in a cell has a `height` delegate method that corresponds to its text dataSource method
*/
/**
* This logic should be consistent with what you return from `attributedTextForCellTopLabelAtIndexPath:`
* The other label height delegate methods should follow similarly
*
* Show a timestamp for every 3rd message
*/
if (indexPath.item % 3 == 0) {
return kJSQMessagesCollectionViewCellLabelHeightDefault;
}
return 0.0f;
}
- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView
layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForMessageBubbleTopLabelAtIndexPath:(NSIndexPath *)indexPath
{
/**
* iOS7-style sender name labels
*/
JSQMessage *currentMessage = [self.demoData.messages objectAtIndex:indexPath.item];
if ([[currentMessage senderId] isEqualToString:self.senderId]) {
return 0.0f;
}
if (indexPath.item - 1 > 0) {
JSQMessage *previousMessage = [self.demoData.messages objectAtIndex:indexPath.item - 1];
if ([[previousMessage senderId] isEqualToString:[currentMessage senderId]]) {
return 0.0f;
}
}
return kJSQMessagesCollectionViewCellLabelHeightDefault;
}
- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView
layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath
{
return 0.0f;
}
#pragma mark - Responding to collection view tap events
- (void)collectionView:(JSQMessagesCollectionView *)collectionView
header:(JSQMessagesLoadEarlierHeaderView *)headerView didTapLoadEarlierMessagesButton:(UIButton *)sender
{
NSLog(@"Load earlier messages!");
}
- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapAvatarImageView:(UIImageView *)avatarImageView atIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"Tapped avatar!");
}
- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapMessageBubbleAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"Tapped message bubble!");
}
- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapCellAtIndexPath:(NSIndexPath *)indexPath touchLocation:(CGPoint)touchLocation
{
NSLog(@"Tapped cell at %@!", NSStringFromCGPoint(touchLocation));
}
@end

View File

@ -1,61 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// Documentation
// http://cocoadocs.org/docsets/JSQMessagesViewController
//
//
// GitHub
// https://github.com/jessesquires/JSQMessagesViewController
//
//
// License
// Copyright (c) 2014 Jesse Squires
// Released under an MIT license: http://opensource.org/licenses/MIT
//
@import Foundation;
@import UIKit;
@import CoreLocation;
#import "JSQMessages.h"
/**
* This is for demo/testing purposes only.
* This object sets up some fake model data.
* Do not actually do anything like this.
*/
static NSString * const kJSQDemoAvatarDisplayNameSquires = @"Jesse Squires";
static NSString * const kJSQDemoAvatarDisplayNameCook = @"Tim Cook";
static NSString * const kJSQDemoAvatarDisplayNameJobs = @"Jobs";
static NSString * const kJSQDemoAvatarDisplayNameWoz = @"Steve Wozniak";
static NSString * const kJSQDemoAvatarIdSquires = @"053496-4509-289";
static NSString * const kJSQDemoAvatarIdCook = @"468-768355-23123";
static NSString * const kJSQDemoAvatarIdJobs = @"707-8956784-57";
static NSString * const kJSQDemoAvatarIdWoz = @"309-41802-93823";
@interface DemoModelData : NSObject
@property (strong, nonatomic) NSMutableArray *messages;
@property (strong, nonatomic) NSDictionary *avatars;
@property (strong, nonatomic) JSQMessagesBubbleImage *outgoingBubbleImageData;
@property (strong, nonatomic) JSQMessagesBubbleImage *incomingBubbleImageData;
@property (strong, nonatomic) NSDictionary *users;
- (void)addPhotoMediaMessage;
- (void)addLocationMediaMessageCompletion:(JSQLocationMediaItemCompletionBlock)completion;
- (void)addVideoMediaMessage;
@end

View File

@ -1,193 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// Documentation
// http://cocoadocs.org/docsets/JSQMessagesViewController
//
//
// GitHub
// https://github.com/jessesquires/JSQMessagesViewController
//
//
// License
// Copyright (c) 2014 Jesse Squires
// Released under an MIT license: http://opensource.org/licenses/MIT
//
#import "DemoModelData.h"
#import "NSUserDefaults+DemoSettings.h"
/**
* This is for demo/testing purposes only.
* This object sets up some fake model data.
* Do not actually do anything like this.
*/
@implementation DemoModelData
- (instancetype)init
{
self = [super init];
if (self) {
if ([NSUserDefaults emptyMessagesSetting]) {
self.messages = [NSMutableArray new];
}
else {
[self loadFakeMessages];
}
/**
* Create avatar images once.
*
* Be sure to create your avatars one time and reuse them for good performance.
*
* If you are not using avatars, ignore this.
*/
JSQMessagesAvatarImage *jsqImage = [JSQMessagesAvatarImageFactory avatarImageWithUserInitials:@"JSQ"
backgroundColor:[UIColor colorWithWhite:0.85f alpha:1.0f]
textColor:[UIColor colorWithWhite:0.60f alpha:1.0f]
font:[UIFont systemFontOfSize:14.0f]
diameter:kJSQMessagesCollectionViewAvatarSizeDefault];
JSQMessagesAvatarImage *cookImage = [JSQMessagesAvatarImageFactory avatarImageWithImage:[UIImage imageNamed:@"demo_avatar_cook"]
diameter:kJSQMessagesCollectionViewAvatarSizeDefault];
JSQMessagesAvatarImage *jobsImage = [JSQMessagesAvatarImageFactory avatarImageWithImage:[UIImage imageNamed:@"demo_avatar_jobs"]
diameter:kJSQMessagesCollectionViewAvatarSizeDefault];
JSQMessagesAvatarImage *wozImage = [JSQMessagesAvatarImageFactory avatarImageWithImage:[UIImage imageNamed:@"demo_avatar_woz"]
diameter:kJSQMessagesCollectionViewAvatarSizeDefault];
self.avatars = @{ kJSQDemoAvatarIdSquires : jsqImage,
kJSQDemoAvatarIdCook : cookImage,
kJSQDemoAvatarIdJobs : jobsImage,
kJSQDemoAvatarIdWoz : wozImage };
self.users = @{ kJSQDemoAvatarIdJobs : kJSQDemoAvatarDisplayNameJobs,
kJSQDemoAvatarIdCook : kJSQDemoAvatarDisplayNameCook,
kJSQDemoAvatarIdWoz : kJSQDemoAvatarDisplayNameWoz,
kJSQDemoAvatarIdSquires : kJSQDemoAvatarDisplayNameSquires };
/**
* Create message bubble images objects.
*
* Be sure to create your bubble images one time and reuse them for good performance.
*
*/
JSQMessagesBubbleImageFactory *bubbleFactory = [[JSQMessagesBubbleImageFactory alloc] init];
self.outgoingBubbleImageData = [bubbleFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleLightGrayColor]];
self.incomingBubbleImageData = [bubbleFactory incomingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleGreenColor]];
}
return self;
}
- (void)loadFakeMessages
{
/**
* Load some fake messages for demo.
*
* You should have a mutable array or orderedSet, or something.
*/
self.messages = [[NSMutableArray alloc] initWithObjects:
[[JSQTextMessage alloc] initWithSenderId:kJSQDemoAvatarIdSquires
senderDisplayName:kJSQDemoAvatarDisplayNameSquires
date:[NSDate distantPast]
text:@"Welcome to JSQMessages: A messaging UI framework for iOS."],
[[JSQTextMessage alloc] initWithSenderId:kJSQDemoAvatarIdWoz
senderDisplayName:kJSQDemoAvatarDisplayNameWoz
date:[NSDate distantPast]
text:@"It is simple, elegant, and easy to use. There are super sweet default settings, but you can customize like crazy."],
[[JSQTextMessage alloc] initWithSenderId:kJSQDemoAvatarIdSquires
senderDisplayName:kJSQDemoAvatarDisplayNameSquires
date:[NSDate distantPast]
text:@"It even has data detectors. You can call me tonight. My cell number is 123-456-7890. My website is www.hexedbits.com."],
[[JSQTextMessage alloc] initWithSenderId:kJSQDemoAvatarIdJobs
senderDisplayName:kJSQDemoAvatarDisplayNameJobs
date:[NSDate date]
text:@"JSQMessagesViewController is nearly an exact replica of the iOS Messages App. And perhaps, better."],
[[JSQTextMessage alloc] initWithSenderId:kJSQDemoAvatarIdCook
senderDisplayName:kJSQDemoAvatarDisplayNameCook
date:[NSDate date]
text:@"It is unit-tested, free, open-source, and documented."],
[[JSQTextMessage alloc] initWithSenderId:kJSQDemoAvatarIdSquires
senderDisplayName:kJSQDemoAvatarDisplayNameSquires
date:[NSDate date]
text:@"Now with media messages!"],
nil];
[self addPhotoMediaMessage];
/**
* Setting to load extra messages for testing/demo
*/
if ([NSUserDefaults extraMessagesSetting]) {
NSArray *copyOfMessages = [self.messages copy];
for (NSUInteger i = 0; i < 4; i++) {
[self.messages addObjectsFromArray:copyOfMessages];
}
}
/**
* Setting to load REALLY long message for testing/demo
* You should see "END" twice
*/
if ([NSUserDefaults longMessageSetting]) {
JSQTextMessage *reallyLongMessage = [JSQTextMessage messageWithSenderId:kJSQDemoAvatarIdSquires
displayName:kJSQDemoAvatarDisplayNameSquires
text:@"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? END Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? END"];
[self.messages addObject:reallyLongMessage];
}
}
- (void)addPhotoMediaMessage
{
JSQPhotoMediaItem *photoItem = [[JSQPhotoMediaItem alloc] initWithImage:[UIImage imageNamed:@"goldengate"]];
JSQMediaMessage *photoMessage = [JSQMediaMessage messageWithSenderId:kJSQDemoAvatarIdSquires
displayName:kJSQDemoAvatarDisplayNameSquires
media:photoItem];
[self.messages addObject:photoMessage];
}
- (void)addLocationMediaMessageCompletion:(JSQLocationMediaItemCompletionBlock)completion
{
CLLocation *ferryBuildingInSF = [[CLLocation alloc] initWithLatitude:37.795313 longitude:-122.393757];
JSQLocationMediaItem *locationItem = [[JSQLocationMediaItem alloc] init];
[locationItem setLocation:ferryBuildingInSF withCompletionHandler:completion];
JSQMediaMessage *locationMessage = [JSQMediaMessage messageWithSenderId:kJSQDemoAvatarIdSquires
displayName:kJSQDemoAvatarDisplayNameSquires
media:locationItem];
[self.messages addObject:locationMessage];
}
- (void)addVideoMediaMessage
{
// don't have a real video, just pretending
NSURL *videoURL = [NSURL URLWithString:@"file://"];
JSQVideoMediaitem *videoItem = [[JSQVideoMediaitem alloc] initWithFileURL:videoURL isReadyToPlay:YES];
JSQMediaMessage *videoMessage = [JSQMediaMessage messageWithSenderId:kJSQDemoAvatarIdSquires
displayName:kJSQDemoAvatarDisplayNameSquires
media:videoItem];
[self.messages addObject:videoMessage];
}
@end

View File

@ -1,42 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// Documentation
// http://cocoadocs.org/docsets/JSQMessagesViewController
//
//
// GitHub
// https://github.com/jessesquires/JSQMessagesViewController
//
//
// License
// Copyright (c) 2014 Jesse Squires
// Released under an MIT license: http://opensource.org/licenses/MIT
//
@import Foundation;
@import UIKit;
/**
* This is for demo/testing purposes only.
*
* This is a terrible idea for a real app.
*/
@interface DemoSettingsViewController : UITableViewController
@property (weak, nonatomic) IBOutlet UISwitch *extraMessagesSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *longMessageSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *emptySwitch;
@property (weak, nonatomic) IBOutlet UISwitch *incomingAvatarsSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *outgoingAvatarsSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *springySwitch;
@end

View File

@ -1,72 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// Documentation
// http://cocoadocs.org/docsets/JSQMessagesViewController
//
//
// GitHub
// https://github.com/jessesquires/JSQMessagesViewController
//
//
// License
// Copyright (c) 2014 Jesse Squires
// Released under an MIT license: http://opensource.org/licenses/MIT
//
#import "DemoSettingsViewController.h"
#import "NSUserDefaults+DemoSettings.h"
/**
* This is for demo/testing purposes only.
*
* This is a terrible idea for a real app.
*/
@implementation DemoSettingsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.extraMessagesSwitch.on = [NSUserDefaults extraMessagesSetting];
self.longMessageSwitch.on = [NSUserDefaults longMessageSetting];
self.emptySwitch.on = [NSUserDefaults emptyMessagesSetting];
self.incomingAvatarsSwitch.on = [NSUserDefaults incomingAvatarSetting];
self.outgoingAvatarsSwitch.on = [NSUserDefaults outgoingAvatarSetting];
self.springySwitch.on = [NSUserDefaults springinessSetting];
}
- (IBAction)didTapSwitch:(UISwitch *)sender
{
if (sender == self.extraMessagesSwitch) {
[NSUserDefaults saveExtraMessagesSetting:sender.on];
}
else if (sender == self.longMessageSwitch) {
[NSUserDefaults saveLongMessageSetting:sender.on];
}
else if (sender == self.emptySwitch) {
[NSUserDefaults saveEmptyMessagesSetting:sender.on];
}
else if (sender == self.incomingAvatarsSwitch) {
[NSUserDefaults saveIncomingAvatarSetting:sender.on];
}
else if (sender == self.outgoingAvatarsSwitch) {
[NSUserDefaults saveOutgoingAvatarSetting:sender.on];
}
else if (sender == self.springySwitch) {
[NSUserDefaults saveSpringinessSetting:sender.on];
}
[[NSUserDefaults standardUserDefaults] synchronize];
}
@end

View File

@ -6,36 +6,18 @@
"filename" : "Icon-Small@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-87.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-Spotlight-iOS7@2x-1.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-120-1.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-120.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-180.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "ipad",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 760 B

After

Width:  |  Height:  |  Size: 760 B

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 947 B

After

Width:  |  Height:  |  Size: 947 B

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -9,11 +9,6 @@
"idiom" : "universal",
"scale" : "2x",
"filename" : "demo_avatar_cook@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "demo_avatar_cook@3x.png"
}
],
"info" : {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

View File

@ -9,11 +9,6 @@
"idiom" : "universal",
"scale" : "2x",
"filename" : "demo_avatar_jobs@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "demo_avatar_jobs@3x.png"
}
],
"info" : {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -9,11 +9,6 @@
"idiom" : "universal",
"scale" : "2x",
"filename" : "demo_avatar_woz@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "demo_avatar_woz@3x.png"
}
],
"info" : {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

View File

@ -1,32 +1,5 @@
{
"images" : [
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "736h",
"filename" : "jsq_messages_splash_55inch.png",
"minimum-system-version" : "8.0",
"orientation" : "portrait",
"scale" : "3x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "736h",
"filename" : "jsq_messages_splash_55inch_landscape.png",
"minimum-system-version" : "8.0",
"orientation" : "landscape",
"scale" : "3x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "667h",
"filename" : "jsq_messages_splash_47inch.png",
"minimum-system-version" : "8.0",
"orientation" : "portrait",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,23 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "goldengate.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "goldengate@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "goldengate@3x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 651 KiB

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// Documentation
@ -16,10 +16,9 @@
// Released under an MIT license: http://opensource.org/licenses/MIT
//
@import Foundation;
@import UIKit;
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@interface JSQAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// Documentation
@ -16,19 +16,12 @@
// Released under an MIT license: http://opensource.org/licenses/MIT
//
#import "AppDelegate.h"
#import "JSQAppDelegate.h"
#import "NSUserDefaults+DemoSettings.h"
@implementation AppDelegate
@implementation JSQAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Load our default settings
[NSUserDefaults saveIncomingAvatarSetting:YES];
[NSUserDefaults saveOutgoingAvatarSetting:YES];
return YES;
}

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// Documentation
@ -16,35 +16,34 @@
// Released under an MIT license: http://opensource.org/licenses/MIT
//
// Import all the things
#import "JSQMessages.h"
#import "DemoModelData.h"
#import "NSUserDefaults+DemoSettings.h"
@class JSQDemoViewController;
@class DemoMessagesViewController;
@protocol JSQDemoViewControllerDelegate <NSObject>
- (void)didDismissJSQDemoViewController:(DemoMessagesViewController *)vc;
- (void)didDismissJSQDemoViewController:(JSQDemoViewController *)vc;
@end
@interface DemoMessagesViewController : JSQMessagesViewController <UIActionSheetDelegate>
@interface JSQDemoViewController : JSQMessagesViewController
@property (weak, nonatomic) id<JSQDemoViewControllerDelegate> delegateModal;
@property (strong, nonatomic) DemoModelData *demoData;
@property (strong, nonatomic) NSMutableArray *messages;
@property (copy, nonatomic) NSDictionary *avatars;
@property (strong, nonatomic) UIImageView *outgoingBubbleImageView;
@property (strong, nonatomic) UIImageView *incomingBubbleImageView;
- (void)receiveMessagePressed:(UIBarButtonItem *)sender;
- (void)closePressed:(UIBarButtonItem *)sender;
// TODO: example of async avatar loading
- (void)setupTestModel;
@end

View File

@ -0,0 +1,480 @@
//
// Created by Jesse Squires
// http://www.hexedbits.com
//
//
// Documentation
// http://cocoadocs.org/docsets/JSQMessagesViewController
//
//
// GitHub
// https://github.com/jessesquires/JSQMessagesViewController
//
//
// License
// Copyright (c) 2014 Jesse Squires
// Released under an MIT license: http://opensource.org/licenses/MIT
//
#import "JSQDemoViewController.h"
static NSString * const kJSQDemoAvatarNameCook = @"Tim Cook";
static NSString * const kJSQDemoAvatarNameJobs = @"Jobs";
static NSString * const kJSQDemoAvatarNameWoz = @"Steve Wozniak";
@implementation JSQDemoViewController
#pragma mark - Demo setup
- (void)setupTestModel
{
/**
* Load some fake messages for demo.
*
* You should have a mutable array or orderedSet, or something.
*/
self.messages = [[NSMutableArray alloc] initWithObjects:
[[JSQMessage alloc] initWithText:@"Welcome to JSQMessages: A messaging UI framework for iOS." sender:self.sender date:[NSDate distantPast]],
[[JSQMessage alloc] initWithText:@"It is simple, elegant, and easy to use. There are super sweet default settings, but you can customize like crazy." sender:kJSQDemoAvatarNameWoz date:[NSDate distantPast]],
[[JSQMessage alloc] initWithText:@"It even has data detectors. You can call me tonight. My cell number is 123-456-7890. My website is www.hexedbits.com." sender:self.sender date:[NSDate distantPast]],
[[JSQMessage alloc] initWithText:@"JSQMessagesViewController is nearly an exact replica of the iOS Messages App. And perhaps, better." sender:kJSQDemoAvatarNameJobs date:[NSDate date]],
[[JSQMessage alloc] initWithText:@"It is unit-tested, free, and open-source." sender:kJSQDemoAvatarNameCook date:[NSDate date]],
[[JSQMessage alloc] initWithText:@"Oh, and there's sweet documentation." sender:self.sender date:[NSDate date]],
nil];
/**
* Create avatar images once.
*
* Be sure to create your avatars one time and reuse them for good performance.
*
* If you are not using avatars, ignore this.
*/
CGFloat outgoingDiameter = self.collectionView.collectionViewLayout.outgoingAvatarViewSize.width;
UIImage *jsqImage = [JSQMessagesAvatarFactory avatarWithUserInitials:@"JSQ"
backgroundColor:[UIColor colorWithWhite:0.85f alpha:1.0f]
textColor:[UIColor colorWithWhite:0.60f alpha:1.0f]
font:[UIFont systemFontOfSize:14.0f]
diameter:outgoingDiameter];
CGFloat incomingDiameter = self.collectionView.collectionViewLayout.incomingAvatarViewSize.width;
UIImage *cookImage = [JSQMessagesAvatarFactory avatarWithImage:[UIImage imageNamed:@"demo_avatar_cook"]
diameter:incomingDiameter];
UIImage *jobsImage = [JSQMessagesAvatarFactory avatarWithImage:[UIImage imageNamed:@"demo_avatar_jobs"]
diameter:incomingDiameter];
UIImage *wozImage = [JSQMessagesAvatarFactory avatarWithImage:[UIImage imageNamed:@"demo_avatar_woz"]
diameter:incomingDiameter];
self.avatars = @{ self.sender : jsqImage,
kJSQDemoAvatarNameCook : cookImage,
kJSQDemoAvatarNameJobs : jobsImage,
kJSQDemoAvatarNameWoz : wozImage };
/**
* Change to add more messages for testing
*/
NSUInteger messagesToAdd = 0;
NSArray *copyOfMessages = [self.messages copy];
for (NSUInteger i = 0; i < messagesToAdd; i++) {
[self.messages addObjectsFromArray:copyOfMessages];
}
/**
* Change to YES to add a super long message for testing
* You should see "END" twice
*/
BOOL addREALLYLongMessage = NO;
if (addREALLYLongMessage) {
JSQMessage *reallyLongMessage = [JSQMessage messageWithText:@"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? END Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? END" sender:self.sender];
[self.messages addObject:reallyLongMessage];
}
}
#pragma mark - View lifecycle
/**
* Override point for customization.
*
* Customize your view.
* Look at the properties on `JSQMessagesViewController` to see what is possible.
*
* Customize your layout.
* Look at the properties on `JSQMessagesCollectionViewFlowLayout` to see what is possible.
*/
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = @"JSQMessages";
self.sender = @"Jesse Squires";
[self setupTestModel];
/**
* Remove camera button since media messages are not yet implemented
*
* self.inputToolbar.contentView.leftBarButtonItem = nil;
*
* Or, you can set a custom `leftBarButtonItem` and a custom `rightBarButtonItem`
*/
/**
* Create bubble images.
*
* Be sure to create your avatars one time and reuse them for good performance.
*
*/
self.outgoingBubbleImageView = [JSQMessagesBubbleImageFactory
outgoingMessageBubbleImageViewWithColor:[UIColor jsq_messageBubbleLightGrayColor]];
self.incomingBubbleImageView = [JSQMessagesBubbleImageFactory
incomingMessageBubbleImageViewWithColor:[UIColor jsq_messageBubbleGreenColor]];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"typing"]
style:UIBarButtonItemStyleBordered
target:self
action:@selector(receiveMessagePressed:)];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.delegateModal) {
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop
target:self
action:@selector(closePressed:)];
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
/**
* Enable/disable springy bubbles, default is NO.
* You must set this from `viewDidAppear:`
* Note: this feature is mostly stable, but still experimental
*/
self.collectionView.collectionViewLayout.springinessEnabled = YES;
}
#pragma mark - Actions
- (void)receiveMessagePressed:(UIBarButtonItem *)sender
{
/**
* The following is simply to simulate received messages for the demo.
* Do not actually do this.
*/
/**
* Set the typing indicator to be shown
*/
self.showTypingIndicator = !self.showTypingIndicator;
/**
* Scroll to actually view the indicator
*/
[self scrollToBottomAnimated:YES];
JSQMessage *copyMessage = [[self.messages lastObject] copy];
if (!copyMessage) {
copyMessage = [JSQMessage messageWithText:@"First received!" sender:kJSQDemoAvatarNameJobs];
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSMutableArray *copyAvatars = [[self.avatars allKeys] mutableCopy];
[copyAvatars removeObject:self.sender];
copyMessage.sender = [copyAvatars objectAtIndex:arc4random_uniform((int)[copyAvatars count])];
/**
* This you should do upon receiving a message:
*
* 1. Play sound (optional)
* 2. Add new id<JSQMessageData> object to your data source
* 3. Call `finishReceivingMessage`
*/
[JSQSystemSoundPlayer jsq_playMessageReceivedSound];
[self.messages addObject:copyMessage];
[self finishReceivingMessage];
});
}
- (void)closePressed:(UIBarButtonItem *)sender
{
[self.delegateModal didDismissJSQDemoViewController:self];
}
#pragma mark - JSQMessagesViewController method overrides
- (void)didPressSendButton:(UIButton *)button
withMessageText:(NSString *)text
sender:(NSString *)sender
date:(NSDate *)date
{
/**
* Sending a message. Your implementation of this method should do *at least* the following:
*
* 1. Play sound (optional)
* 2. Add new id<JSQMessageData> object to your data source
* 3. Call `finishSendingMessage`
*/
[JSQSystemSoundPlayer jsq_playMessageSentSound];
JSQMessage *message = [[JSQMessage alloc] initWithText:text sender:sender date:date];
[self.messages addObject:message];
[self finishSendingMessage];
}
- (void)didPressAccessoryButton:(UIButton *)sender
{
NSLog(@"Camera pressed!");
/**
* Accessory button has no default functionality, yet.
*/
}
#pragma mark - JSQMessages CollectionView DataSource
- (id<JSQMessageData>)collectionView:(JSQMessagesCollectionView *)collectionView messageDataForItemAtIndexPath:(NSIndexPath *)indexPath
{
return [self.messages objectAtIndex:indexPath.item];
}
- (UIImageView *)collectionView:(JSQMessagesCollectionView *)collectionView bubbleImageViewForItemAtIndexPath:(NSIndexPath *)indexPath
{
/**
* You may return nil here if you do not want bubbles.
* In this case, you should set the background color of your collection view cell's textView.
*/
/**
* Reuse created bubble images, but create new imageView to add to each cell
* Otherwise, each cell would be referencing the same imageView and bubbles would disappear from cells
*/
JSQMessage *message = [self.messages objectAtIndex:indexPath.item];
if ([message.sender isEqualToString:self.sender]) {
return [[UIImageView alloc] initWithImage:self.outgoingBubbleImageView.image
highlightedImage:self.outgoingBubbleImageView.highlightedImage];
}
return [[UIImageView alloc] initWithImage:self.incomingBubbleImageView.image
highlightedImage:self.incomingBubbleImageView.highlightedImage];
}
- (UIImageView *)collectionView:(JSQMessagesCollectionView *)collectionView avatarImageViewForItemAtIndexPath:(NSIndexPath *)indexPath
{
/**
* Return `nil` here if you do not want avatars.
* If you do return `nil`, be sure to do the following in `viewDidLoad`:
*
* self.collectionView.collectionViewLayout.incomingAvatarViewSize = CGSizeZero;
* self.collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero;
*
* It is possible to have only outgoing avatars or only incoming avatars, too.
*/
/**
* Reuse created avatar images, but create new imageView to add to each cell
* Otherwise, each cell would be referencing the same imageView and avatars would disappear from cells
*
* Note: these images will be sized according to these values:
*
* self.collectionView.collectionViewLayout.incomingAvatarViewSize
* self.collectionView.collectionViewLayout.outgoingAvatarViewSize
*
* Override the defaults in `viewDidLoad`
*/
JSQMessage *message = [self.messages objectAtIndex:indexPath.item];
UIImage *avatarImage = [self.avatars objectForKey:message.sender];
return [[UIImageView alloc] initWithImage:avatarImage];
}
- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath
{
/**
* This logic should be consistent with what you return from `heightForCellTopLabelAtIndexPath:`
* The other label text delegate methods should follow a similar pattern.
*
* Show a timestamp for every 3rd message
*/
if (indexPath.item % 3 == 0) {
JSQMessage *message = [self.messages objectAtIndex:indexPath.item];
return [[JSQMessagesTimestampFormatter sharedFormatter] attributedTimestampForDate:message.date];
}
return nil;
}
- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForMessageBubbleTopLabelAtIndexPath:(NSIndexPath *)indexPath
{
JSQMessage *message = [self.messages objectAtIndex:indexPath.item];
/**
* iOS7-style sender name labels
*/
if ([message.sender isEqualToString:self.sender]) {
return nil;
}
if (indexPath.item - 1 > 0) {
JSQMessage *previousMessage = [self.messages objectAtIndex:indexPath.item - 1];
if ([[previousMessage sender] isEqualToString:message.sender]) {
return nil;
}
}
/**
* Don't specify attributes to use the defaults.
*/
return [[NSAttributedString alloc] initWithString:message.sender];
}
- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath
{
return nil;
}
#pragma mark - UICollectionView DataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [self.messages count];
}
- (UICollectionViewCell *)collectionView:(JSQMessagesCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
/**
* Override point for customizing cells
*/
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
/**
* Configure almost *anything* on the cell
*
* Text colors, label text, label colors, etc.
*
*
* DO NOT set `cell.textView.font` !
* Instead, you need to set `self.collectionView.collectionViewLayout.messageBubbleFont` to the font you want in `viewDidLoad`
*
*
* DO NOT manipulate cell layout information!
* Instead, override the properties you want on `self.collectionView.collectionViewLayout` from `viewDidLoad`
*/
JSQMessage *msg = [self.messages objectAtIndex:indexPath.item];
if ([msg.sender isEqualToString:self.sender]) {
cell.textView.textColor = [UIColor blackColor];
}
else {
cell.textView.textColor = [UIColor whiteColor];
}
cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor,
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };
return cell;
}
#pragma mark - JSQMessages collection view flow layout delegate
#pragma mark - Adjusting cell label heights
- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView
layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath
{
/**
* Each label in a cell has a `height` delegate method that corresponds to its text dataSource method
*/
/**
* This logic should be consistent with what you return from `attributedTextForCellTopLabelAtIndexPath:`
* The other label height delegate methods should follow similarly
*
* Show a timestamp for every 3rd message
*/
if (indexPath.item % 3 == 0) {
return kJSQMessagesCollectionViewCellLabelHeightDefault;
}
return 0.0f;
}
- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView
layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForMessageBubbleTopLabelAtIndexPath:(NSIndexPath *)indexPath
{
/**
* iOS7-style sender name labels
*/
JSQMessage *currentMessage = [self.messages objectAtIndex:indexPath.item];
if ([[currentMessage sender] isEqualToString:self.sender]) {
return 0.0f;
}
if (indexPath.item - 1 > 0) {
JSQMessage *previousMessage = [self.messages objectAtIndex:indexPath.item - 1];
if ([[previousMessage sender] isEqualToString:[currentMessage sender]]) {
return 0.0f;
}
}
return kJSQMessagesCollectionViewCellLabelHeightDefault;
}
- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView
layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath
{
return 0.0f;
}
#pragma mark - Responding to collection view tap events
- (void)collectionView:(JSQMessagesCollectionView *)collectionView
header:(JSQMessagesLoadEarlierHeaderView *)headerView didTapLoadEarlierMessagesButton:(UIButton *)sender
{
NSLog(@"Load earlier messages!");
}
- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapAvatarImageView:(UIImageView *)avatarImageView atIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"Tapped avatar!");
}
- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapMessageBubbleAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"Tapped message bubble!");
}
- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapCellAtIndexPath:(NSIndexPath *)indexPath touchLocation:(CGPoint)touchLocation
{
NSLog(@"Tapped cell at %@!", NSStringFromCGPoint(touchLocation));
}
@end

View File

@ -4,28 +4,30 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Messages</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.hexedbits.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>com.hexedbits.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>6.0.0</string>
<string>5.3.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>6.0.0</string>
<string>5.3.2</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIMainStoryboardFile~ipad</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>

View File

@ -0,0 +1,19 @@
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#import <Availability.h>
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
// Make NSLog more useful and pretty
#define NSLog(__FORMAT__, ...) NSLog((@"%s [Line %d] " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// Documentation
@ -16,12 +16,11 @@
// Released under an MIT license: http://opensource.org/licenses/MIT
//
@import Foundation;
@import UIKit;
#import <UIKit/UIKit.h>
#import "DemoMessagesViewController.h"
#import "JSQDemoViewController.h"
@interface TableViewController : UITableViewController <JSQDemoViewControllerDelegate>
@interface JSQTableViewController : UITableViewController <JSQDemoViewControllerDelegate>
- (IBAction)unwindSegue:(UIStoryboardSegue *)sender;

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// Documentation
@ -16,9 +16,9 @@
// Released under an MIT license: http://opensource.org/licenses/MIT
//
#import "TableViewController.h"
#import "JSQTableViewController.h"
@implementation TableViewController
@implementation JSQTableViewController
#pragma mark - View lifecycle
@ -38,15 +38,11 @@
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 2) {
return 1;
}
return 2;
}
@ -79,29 +75,10 @@
break;
}
}
else if (indexPath.section == 2) {
switch (indexPath.row) {
case 0:
cell.textLabel.text = @"Settings";
break;
}
}
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
switch (section) {
case 0:
return @"Presentation";
case 2:
return @"Demo options";
default:
return nil;
}
}
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
return (section == [tableView numberOfSections] - 1) ? @"Copyright © 2014\nJesse Squires\nMIT License" : nil;
@ -118,7 +95,7 @@
break;
case 1:
{
DemoMessagesViewController *vc = [DemoMessagesViewController messagesViewController];
JSQDemoViewController *vc = [JSQDemoViewController messagesViewController];
[self.navigationController pushViewController:vc animated:YES];
}
break;
@ -131,7 +108,7 @@
break;
case 1:
{
DemoMessagesViewController *vc = [DemoMessagesViewController messagesViewController];
JSQDemoViewController *vc = [JSQDemoViewController messagesViewController];
vc.delegateModal = self;
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:vc];
[self presentViewController:nc animated:YES completion:nil];
@ -139,13 +116,6 @@
break;
}
}
else if (indexPath.section == 2) {
switch (indexPath.row) {
case 0:
[self performSegueWithIdentifier:@"SegueToSettings" sender:self];
break;
}
}
}
#pragma mark - Segues
@ -154,7 +124,7 @@
{
if ([segue.identifier isEqualToString:@"segueModalDemoVC"]) {
UINavigationController *nc = segue.destinationViewController;
DemoMessagesViewController *vc = (DemoMessagesViewController *)nc.topViewController;
JSQDemoViewController *vc = (JSQDemoViewController *)nc.topViewController;
vc.delegateModal = self;
}
}
@ -163,7 +133,7 @@
#pragma mark - Demo delegate
- (void)didDismissJSQDemoViewController:(DemoMessagesViewController *)vc
- (void)didDismissJSQDemoViewController:(JSQDemoViewController *)vc
{
[self dismissViewControllerAnimated:YES completion:nil];
}

View File

@ -1,41 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// Documentation
// http://cocoadocs.org/docsets/JSQMessagesViewController
//
//
// GitHub
// https://github.com/jessesquires/JSQMessagesViewController
//
//
// License
// Copyright (c) 2014 Jesse Squires
// Released under an MIT license: http://opensource.org/licenses/MIT
//
@import Foundation;
@interface NSUserDefaults (DemoSettings)
+ (void)saveExtraMessagesSetting:(BOOL)value;
+ (BOOL)extraMessagesSetting;
+ (void)saveLongMessageSetting:(BOOL)value;
+ (BOOL)longMessageSetting;
+ (void)saveEmptyMessagesSetting:(BOOL)value;
+ (BOOL)emptyMessagesSetting;
+ (void)saveSpringinessSetting:(BOOL)value;
+ (BOOL)springinessSetting;
+ (void)saveOutgoingAvatarSetting:(BOOL)value;
+ (BOOL)outgoingAvatarSetting;
+ (void)saveIncomingAvatarSetting:(BOOL)value;
+ (BOOL)incomingAvatarSetting;
@end

View File

@ -1,91 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// Documentation
// http://cocoadocs.org/docsets/JSQMessagesViewController
//
//
// GitHub
// https://github.com/jessesquires/JSQMessagesViewController
//
//
// License
// Copyright (c) 2014 Jesse Squires
// Released under an MIT license: http://opensource.org/licenses/MIT
//
#import "NSUserDefaults+DemoSettings.h"
static NSString * const kSettingExtraMessages = @"kSettingExtraMessages";
static NSString * const kSettingLongMessage = @"kSettingLongMessage";
static NSString * const kSettingEmptyMessages = @"kSettingEmptyMessages";
static NSString * const kSettingSpringiness = @"kSettingSpringiness";
static NSString * const kSettingIncomingAvatar = @"kSettingIncomingAvatar";
static NSString * const kSettingOutgoingAvatar = @"kSettingOutgoingAvatar";
@implementation NSUserDefaults (DemoSettings)
+ (void)saveExtraMessagesSetting:(BOOL)value
{
[[NSUserDefaults standardUserDefaults] setBool:value forKey:kSettingExtraMessages];
}
+ (BOOL)extraMessagesSetting
{
return [[NSUserDefaults standardUserDefaults] boolForKey:kSettingExtraMessages];
}
+ (void)saveLongMessageSetting:(BOOL)value
{
[[NSUserDefaults standardUserDefaults] setBool:value forKey:kSettingLongMessage];
}
+ (BOOL)longMessageSetting
{
return [[NSUserDefaults standardUserDefaults] boolForKey:kSettingLongMessage];
}
+ (void)saveEmptyMessagesSetting:(BOOL)value
{
[[NSUserDefaults standardUserDefaults] setBool:value forKey:kSettingEmptyMessages];
}
+ (BOOL)emptyMessagesSetting
{
return [[NSUserDefaults standardUserDefaults] boolForKey:kSettingEmptyMessages];
}
+ (void)saveSpringinessSetting:(BOOL)value
{
[[NSUserDefaults standardUserDefaults] setBool:value forKey:kSettingSpringiness];
}
+ (BOOL)springinessSetting
{
return [[NSUserDefaults standardUserDefaults] boolForKey:kSettingSpringiness];
}
+ (void)saveOutgoingAvatarSetting:(BOOL)value
{
[[NSUserDefaults standardUserDefaults] setBool:value forKey:kSettingOutgoingAvatar];
}
+ (BOOL)outgoingAvatarSetting
{
return [[NSUserDefaults standardUserDefaults] boolForKey:kSettingOutgoingAvatar];
}
+ (void)saveIncomingAvatarSetting:(BOOL)value
{
[[NSUserDefaults standardUserDefaults] setBool:value forKey:kSettingIncomingAvatar];
}
+ (BOOL)incomingAvatarSetting
{
return [[NSUserDefaults standardUserDefaults] boolForKey:kSettingIncomingAvatar];
}
@end

View File

@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

6
JSQMessagesDemo/main.m Normal file → Executable file
View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// Documentation
@ -18,11 +18,11 @@
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "JSQAppDelegate.h"
int main(int argc, char * argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
return UIApplicationMain(argc, argv, nil, NSStringFromClass([JSQAppDelegate class]));
}
}

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "NSString+JSQMessages.h"

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "UIColor+JSQMessages.h"

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "UIImage+JSQMessages.h"

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "UIView+JSQMessages.h"

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesKeyboardController.h"

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,12 +8,11 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesViewController.h"
#import "DemoMessagesViewController.h"
#import "JSQDemoViewController.h"
@interface JSQMessagesViewController ()
@ -54,23 +53,21 @@
XCTAssertNotNil(vc.collectionView, @"Collection view should not be nil");
XCTAssertNotNil(vc.inputToolbar, @"Input toolbar should not be nil");
XCTAssertEqualObjects(vc.senderId, @"JSQDefaultSender", @"Property should be equal to default value");
XCTAssertEqualObjects(vc.senderDisplayName, @"JSQDefaultSender", @"Property should be equal to default value");
XCTAssertEqualObjects(vc.sender, @"JSQDefaultSender", @"Property should be equal to default value");
XCTAssertEqual(vc.automaticallyAdjustsScrollViewInsets, YES, @"Property should be equal to default value");
XCTAssertEqualObjects(vc.incomingCellIdentifier, [JSQMessagesCollectionViewCellIncoming cellReuseIdentifier], @"Property should be equal to default value");
XCTAssertEqualObjects(vc.outgoingCellIdentifier, [JSQMessagesCollectionViewCellOutgoing cellReuseIdentifier], @"Property should be equal to default value");
XCTAssertEqualObjects(vc.typingIndicatorColor, [UIColor jsq_messageBubbleLightGrayColor], @"Property should be equal to default value");
XCTAssertEqual(vc.showTypingIndicator, NO, @"Property should be equal to default value");
XCTAssertEqual(vc.showLoadEarlierMessagesHeader, NO, @"Property should be equal to default value");
}
- (void)testJSQMessagesViewControllerSubclassInitProgramatically
{
DemoMessagesViewController *demoVC = [DemoMessagesViewController messagesViewController];
JSQDemoViewController *demoVC = [JSQDemoViewController messagesViewController];
[demoVC view];
XCTAssertNotNil(demoVC, @"View controller should not be nil");
XCTAssertTrue([demoVC isKindOfClass:[DemoMessagesViewController class]], @"View controller should be kind of class: %@", [DemoMessagesViewController class]);
XCTAssertTrue([demoVC isKindOfClass:[JSQDemoViewController class]], @"View controller should be kind of class: %@", [JSQDemoViewController class]);
XCTAssertNotNil(demoVC.view, @"View should not be nil");
XCTAssertNotNil(demoVC.collectionView, @"Collection view should not be nil");
XCTAssertNotNil(demoVC.inputToolbar, @"Input toolbar should not be nil");
@ -81,10 +78,10 @@
UIStoryboard *mainSB = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
XCTAssertNotNil(mainSB, @"Storyboard should not be nil");
DemoMessagesViewController *demoVC = [mainSB instantiateViewControllerWithIdentifier:@"DemoVC"];
JSQDemoViewController *demoVC = [mainSB instantiateViewControllerWithIdentifier:@"DemoVC"];
[demoVC view];
XCTAssertNotNil(demoVC, @"View controller should not be nil");
XCTAssertTrue([demoVC isKindOfClass:[DemoMessagesViewController class]], @"View controller should be kind of class: %@", [DemoMessagesViewController class]);
XCTAssertTrue([demoVC isKindOfClass:[JSQDemoViewController class]], @"View controller should be kind of class: %@", [JSQDemoViewController class]);
XCTAssertNotNil(demoVC.view, @"View should not be nil");
XCTAssertNotNil(demoVC.collectionView, @"Collection view should not be nil");
XCTAssertNotNil(demoVC.inputToolbar, @"Input toolbar should not be nil");

View File

@ -0,0 +1,59 @@
//
// Created by Jesse Squires
// http://www.hexedbits.com
//
//
// MIT License
// Copyright (c) 2014 Jesse Squires
// http://opensource.org/licenses/MIT
//
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesAvatarFactory.h"
@interface JSQMessagesAvatarFactoryTests : XCTestCase
@end
@implementation JSQMessagesAvatarFactoryTests
- (void)setUp
{
[super setUp];
}
- (void)tearDown
{
[super tearDown];
}
- (void)testAvatarImage
{
UIImage *image = [UIImage imageNamed:@"demo_avatar_jobs"];
XCTAssertNotNil(image, @"Image should not be nil");
CGFloat diameter = 50.0f;
UIImage *avatar = [JSQMessagesAvatarFactory avatarWithImage:image diameter:diameter];
XCTAssertNotNil(avatar, @"Avatar should not be nil");
XCTAssertTrue(CGSizeEqualToSize(avatar.size, CGSizeMake(diameter, diameter)), @"Avatar size should be equal to diameter");
XCTAssertEqual(avatar.scale, image.scale, @"Avatar scale should be equal to original image scale");
}
- (void)testAvatarInitialsImage
{
CGFloat diameter = 50.0f;
UIImage *avatar = [JSQMessagesAvatarFactory avatarWithUserInitials:@"JSQ"
backgroundColor:[UIColor lightGrayColor]
textColor:[UIColor darkGrayColor]
font:[UIFont systemFontOfSize:13.0f]
diameter:diameter];
XCTAssertNotNil(avatar, @"Avatar should not be nil");
XCTAssertTrue(CGSizeEqualToSize(avatar.size, CGSizeMake(diameter, diameter)), @"Avatar size should be equal to diameter");
XCTAssertEqual(avatar.scale, [UIScreen mainScreen].scale, @"Avatar scale should be equal to screen scale");
}
@end

View File

@ -1,74 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// MIT License
// Copyright (c) 2014 Jesse Squires
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import "JSQMessagesAvatarImageFactory.h"
@interface JSQMessagesAvatarImageFactoryTests : XCTestCase
@end
@implementation JSQMessagesAvatarImageFactoryTests
- (void)setUp
{
[super setUp];
}
- (void)tearDown
{
[super tearDown];
}
- (void)testAvatarImage
{
UIImage *image = [UIImage imageNamed:@"demo_avatar_jobs"];
XCTAssertNotNil(image, @"Image should not be nil");
CGFloat diameter = 50.0f;
JSQMessagesAvatarImage *avatar = [JSQMessagesAvatarImageFactory avatarImageWithPlaceholder:image diameter:diameter];
XCTAssertNotNil(avatar, @"Avatar should not be nil");
XCTAssertTrue(CGSizeEqualToSize(avatar.avatarPlaceholderImage.size, CGSizeMake(diameter, diameter)), @"Avatar size should be equal to diameter");
XCTAssertEqual(avatar.avatarPlaceholderImage.scale, [UIScreen mainScreen].scale, @"Avatar scale should be equal to screen scale");
avatar.avatarImage = [JSQMessagesAvatarImageFactory circularAvatarImage:image withDiameter:diameter];
XCTAssertTrue(CGSizeEqualToSize(avatar.avatarImage.size, CGSizeMake(diameter, diameter)), @"Avatar size should be equal to diameter");
XCTAssertEqual(avatar.avatarImage.scale, [UIScreen mainScreen].scale, @"Avatar scale should be equal to screen scale");
avatar.avatarHighlightedImage = [JSQMessagesAvatarImageFactory circularAvatarHighlightedImage:image withDiameter:diameter];
XCTAssertTrue(CGSizeEqualToSize(avatar.avatarHighlightedImage.size, CGSizeMake(diameter, diameter)), @"Avatar size should be equal to diameter");
XCTAssertEqual(avatar.avatarHighlightedImage.scale, [UIScreen mainScreen].scale, @"Avatar scale should be equal to screen scale");
}
- (void)testAvatarInitialsImage
{
CGFloat diameter = 50.0f;
JSQMessagesAvatarImage *avatar = [JSQMessagesAvatarImageFactory avatarImageWithUserInitials:@"JSQ"
backgroundColor:[UIColor lightGrayColor]
textColor:[UIColor darkGrayColor]
font:[UIFont systemFontOfSize:13.0f]
diameter:diameter];
XCTAssertNotNil(avatar, @"Avatar should not be nil");
XCTAssertTrue(CGSizeEqualToSize(avatar.avatarImage.size, CGSizeMake(diameter, diameter)), @"Avatar size should be equal to diameter");
XCTAssertEqual(avatar.avatarImage.scale, [UIScreen mainScreen].scale, @"Avatar scale should be equal to screen scale");
XCTAssertTrue(CGSizeEqualToSize(avatar.avatarHighlightedImage.size, CGSizeMake(diameter, diameter)), @"Avatar size should be equal to diameter");
XCTAssertEqual(avatar.avatarHighlightedImage.scale, [UIScreen mainScreen].scale, @"Avatar scale should be equal to screen scale");
XCTAssertTrue(CGSizeEqualToSize(avatar.avatarPlaceholderImage.size, CGSizeMake(diameter, diameter)), @"Avatar size should be equal to diameter");
XCTAssertEqual(avatar.avatarPlaceholderImage.scale, [UIScreen mainScreen].scale, @"Avatar scale should be equal to screen scale");
}
@end

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,15 +8,13 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesBubbleImageFactory.h"
@interface JSQMessagesBubbleImageFactoryTests : XCTestCase
@property (strong, nonatomic) JSQMessagesBubbleImageFactory *factory;
@end
@ -25,12 +23,10 @@
- (void)setUp
{
[super setUp];
self.factory = [[JSQMessagesBubbleImageFactory alloc] init];
}
- (void)tearDown
{
self.factory = nil;
[super tearDown];
}
@ -42,21 +38,25 @@
CGPoint center = CGPointMake(bubble.size.width / 2.0f, bubble.size.height / 2.0f);
UIEdgeInsets capInsets = UIEdgeInsetsMake(center.y, center.x, center.y, center.x);
JSQMessagesBubbleImage *bubbleImage = [self.factory outgoingMessagesBubbleImageWithColor:[UIColor lightGrayColor]];
XCTAssertNotNil(bubbleImage, @"Bubble image should not be nil");
XCTAssertNotNil(bubbleImage.messageBubbleImage, "Image should not be nil");
XCTAssertEqual(bubbleImage.messageBubbleImage.scale, bubble.scale, @"Image scale should equal bubble image scale");
XCTAssertEqual(bubbleImage.messageBubbleImage.imageOrientation, bubble.imageOrientation, @"Image orientation should equal bubble image orientation");
XCTAssertTrue(bubbleImage.messageBubbleImage.resizingMode == UIImageResizingModeStretch, @"Image should be stretchable");
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(bubbleImage.messageBubbleImage.capInsets, capInsets), @"Image capInsets should be equal to capInsets");
UIImageView *imageView = [JSQMessagesBubbleImageFactory outgoingMessageBubbleImageViewWithColor:[UIColor lightGrayColor]];
XCTAssertNotNil(imageView, @"ImageView should not be nil");
XCTAssertEqualObjects(imageView.backgroundColor, [UIColor whiteColor], @"ImageView should have white background color");
XCTAssertTrue(CGSizeEqualToSize(imageView.frame.size, bubble.size), @"ImageView size should equal bubble size");
XCTAssertNotNil(bubbleImage.messageBubbleHighlightedImage, @"Highlighted image should not be nil");
XCTAssertEqual(bubbleImage.messageBubbleHighlightedImage.scale, bubble.scale, @"HighlightedImage scale should equal bubble image scale");
XCTAssertEqual(bubbleImage.messageBubbleHighlightedImage.imageOrientation, bubble.imageOrientation, @"HighlightedImage orientation should equal bubble image orientation");
XCTAssertTrue(bubbleImage.messageBubbleHighlightedImage.resizingMode == UIImageResizingModeStretch, @"HighlightedImage should be stretchable");
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(bubbleImage.messageBubbleHighlightedImage.capInsets, capInsets), @"HighlightedImage capInsets should be equal to capInsets");
XCTAssertNotNil(imageView.image, @"Image should not be nil");
XCTAssertEqual(imageView.image.scale, bubble.scale, @"Image scale should equal bubble image scale");
XCTAssertEqual(imageView.image.imageOrientation, bubble.imageOrientation, @"Image orientation should equal bubble image orientation");
XCTAssertTrue(imageView.image.resizingMode == UIImageResizingModeStretch, @"Image should be stretchable");
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(imageView.image.capInsets, capInsets), @"Image capInsets should be equal to capInsets");
XCTAssertNotNil(imageView.highlightedImage, @"HighlightedImage should not be nil");
XCTAssertEqual(imageView.highlightedImage.scale, bubble.scale, @"HighlightedImage scale should equal bubble image scale");
XCTAssertEqual(imageView.highlightedImage.imageOrientation, bubble.imageOrientation, @"HighlightedImage orientation should equal bubble image orientation");
XCTAssertTrue(imageView.highlightedImage.resizingMode == UIImageResizingModeStretch, @"HighlightedImage should be stretchable");
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(imageView.highlightedImage.capInsets, capInsets), @"HighlightedImage capInsets should be equal to capInsets");
}
- (void)testIncomingMessageBubbleImageView
@ -67,67 +67,25 @@
CGPoint center = CGPointMake(bubble.size.width / 2.0f, bubble.size.height / 2.0f);
UIEdgeInsets capInsets = UIEdgeInsetsMake(center.y, center.x, center.y, center.x);
JSQMessagesBubbleImage *bubbleImage = [self.factory incomingMessagesBubbleImageWithColor:[UIColor lightGrayColor]];
XCTAssertNotNil(bubbleImage, @"Bubble image should not be nil");
XCTAssertNotNil(bubbleImage.messageBubbleImage, "Image should not be nil");
XCTAssertEqual(bubbleImage.messageBubbleImage.scale, bubble.scale, @"Image scale should equal bubble image scale");
XCTAssertEqual(bubbleImage.messageBubbleImage.imageOrientation, UIImageOrientationUpMirrored, @"Image orientation should be flipped");
XCTAssertTrue(bubbleImage.messageBubbleImage.resizingMode == UIImageResizingModeStretch, @"Image should be stretchable");
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(bubbleImage.messageBubbleImage.capInsets, capInsets), @"Image capInsets should be equal to capInsets");
UIImageView *imageView = [JSQMessagesBubbleImageFactory incomingMessageBubbleImageViewWithColor:[UIColor lightGrayColor]];
XCTAssertNotNil(imageView, @"ImageView should not be nil");
XCTAssertEqualObjects(imageView.backgroundColor, [UIColor whiteColor], @"ImageView should have white background color");
XCTAssertTrue(CGSizeEqualToSize(imageView.frame.size, bubble.size), @"ImageView size should equal bubble size");
XCTAssertNotNil(bubbleImage.messageBubbleHighlightedImage, @"Highlighted image should not be nil");
XCTAssertEqual(bubbleImage.messageBubbleHighlightedImage.scale, bubble.scale, @"HighlightedImage scale should equal bubble image scale");
XCTAssertEqual(bubbleImage.messageBubbleHighlightedImage.imageOrientation, UIImageOrientationUpMirrored, @"Image orientation should be flipped");
XCTAssertTrue(bubbleImage.messageBubbleHighlightedImage.resizingMode == UIImageResizingModeStretch, @"HighlightedImage should be stretchable");
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(bubbleImage.messageBubbleHighlightedImage.capInsets, capInsets), @"HighlightedImage capInsets should be equal to capInsets");
}
- (void)testCustomOutgoingMessageBubbleImageView
{
UIImage *bubble = [UIImage imageNamed:@"clip"];
XCTAssertNotNil(bubble, @"Bubble image should not be nil");
XCTAssertNotNil(imageView.image, @"Image should not be nil");
XCTAssertEqual(imageView.image.scale, bubble.scale, @"Image scale should equal bubble image scale");
XCTAssertEqual(imageView.image.imageOrientation, UIImageOrientationUpMirrored, @"Image orientation should be flipped");
XCTAssertTrue(imageView.image.resizingMode == UIImageResizingModeStretch, @"Image should be stretchable");
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(imageView.image.capInsets, capInsets), @"Image capInsets should be equal to capInsets");
UIEdgeInsets capInsets = UIEdgeInsetsMake(1, 1, 1, 1);
JSQMessagesBubbleImageFactory *factory = [[JSQMessagesBubbleImageFactory alloc] initWithBubbleImage:bubble capInsets:capInsets];
JSQMessagesBubbleImage *bubbleImage = [factory outgoingMessagesBubbleImageWithColor:[UIColor lightGrayColor]];
XCTAssertNotNil(bubbleImage, @"Bubble image should not be nil");
XCTAssertNotNil(bubbleImage.messageBubbleImage, "Image should not be nil");
XCTAssertEqual(bubbleImage.messageBubbleImage.scale, bubble.scale, @"Image scale should equal bubble image scale");
XCTAssertEqual(bubbleImage.messageBubbleImage.imageOrientation, bubble.imageOrientation, @"Image orientation should equal bubble image orientation");
XCTAssertTrue(bubbleImage.messageBubbleImage.resizingMode == UIImageResizingModeStretch, @"Image should be stretchable");
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(bubbleImage.messageBubbleImage.capInsets, capInsets), @"Image capInsets should be equal to capInsets");
XCTAssertNotNil(bubbleImage.messageBubbleHighlightedImage, @"Highlighted image should not be nil");
XCTAssertEqual(bubbleImage.messageBubbleHighlightedImage.scale, bubble.scale, @"HighlightedImage scale should equal bubble image scale");
XCTAssertEqual(bubbleImage.messageBubbleHighlightedImage.imageOrientation, bubble.imageOrientation, @"HighlightedImage orientation should equal bubble image orientation");
XCTAssertTrue(bubbleImage.messageBubbleHighlightedImage.resizingMode == UIImageResizingModeStretch, @"HighlightedImage should be stretchable");
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(bubbleImage.messageBubbleHighlightedImage.capInsets, capInsets), @"HighlightedImage capInsets should be equal to capInsets");
}
- (void)testCustomIncomingMessageBubbleImageView
{
UIImage *bubble = [UIImage imageNamed:@"clip"];
XCTAssertNotNil(bubble, @"Bubble image should not be nil");
UIEdgeInsets capInsets = UIEdgeInsetsMake(1, 1, 1, 1);
JSQMessagesBubbleImageFactory *factory = [[JSQMessagesBubbleImageFactory alloc] initWithBubbleImage:bubble capInsets:capInsets];
JSQMessagesBubbleImage *bubbleImage = [factory incomingMessagesBubbleImageWithColor:[UIColor lightGrayColor]];
XCTAssertNotNil(bubbleImage, @"Bubble image should not be nil");
XCTAssertNotNil(bubbleImage.messageBubbleImage, "Image should not be nil");
XCTAssertEqual(bubbleImage.messageBubbleImage.scale, bubble.scale, @"Image scale should equal bubble image scale");
XCTAssertEqual(bubbleImage.messageBubbleImage.imageOrientation, UIImageOrientationUpMirrored, @"Image orientation should be flipped");
XCTAssertTrue(bubbleImage.messageBubbleImage.resizingMode == UIImageResizingModeStretch, @"Image should be stretchable");
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(bubbleImage.messageBubbleImage.capInsets, capInsets), @"Image capInsets should be equal to capInsets");
XCTAssertNotNil(bubbleImage.messageBubbleHighlightedImage, @"Highlighted image should not be nil");
XCTAssertEqual(bubbleImage.messageBubbleHighlightedImage.scale, bubble.scale, @"HighlightedImage scale should equal bubble image scale");
XCTAssertEqual(bubbleImage.messageBubbleHighlightedImage.imageOrientation, UIImageOrientationUpMirrored, @"Image orientation should be flipped");
XCTAssertTrue(bubbleImage.messageBubbleHighlightedImage.resizingMode == UIImageResizingModeStretch, @"HighlightedImage should be stretchable");
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(bubbleImage.messageBubbleHighlightedImage.capInsets, capInsets), @"HighlightedImage capInsets should be equal to capInsets");
XCTAssertNotNil(imageView.highlightedImage, @"HighlightedImage should not be nil");
XCTAssertEqual(imageView.highlightedImage.scale, bubble.scale, @"HighlightedImage scale should equal bubble image scale");
XCTAssertEqual(imageView.highlightedImage.imageOrientation, UIImageOrientationUpMirrored, @"HighlightedImage orientation should be flipped");
XCTAssertTrue(imageView.highlightedImage.resizingMode == UIImageResizingModeStretch, @"HighlightedImage should be stretchable");
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(imageView.highlightedImage.capInsets, capInsets), @"HighlightedImage capInsets should be equal to capInsets");
}
@end

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesTimestampFormatter.h"

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesToolbarButtonFactory.h"

View File

@ -5,13 +5,11 @@
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.hexedbits.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>com.hexedbits.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesCollectionViewFlowLayout.h"

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesCollectionViewLayoutAttributes.h"

View File

@ -1,112 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// MIT License
// Copyright (c) 2014 Jesse Squires
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <OCMock/OCMock.h>
#import "JSQMediaMessage.h"
// Fake media object for testing
@interface FakeMedia : NSObject <JSQMessageMediaData, NSCoding>
@end
@implementation FakeMedia
- (UIView *)mediaView { return [UIView new]; }
- (UIView *)mediaPlaceholderView { return [self mediaView]; }
- (CGSize)mediaViewDisplaySize { return CGSizeMake(50, 50); }
- (void)encodeWithCoder:(NSCoder *)aCoder { }
- (id)initWithCoder:(NSCoder *)aDecoder { return [self init]; }
- (BOOL)isEqual:(id)object { return YES; }
@end
@interface JSQMediaMessageTests : XCTestCase
@property (strong, nonatomic) NSString *senderId;
@property (strong, nonatomic) NSString *senderDisplayName;
@property (strong, nonatomic) NSDate *date;
@property (strong, nonatomic) id<JSQMessageMediaData> mockMediaData;
@end
@implementation JSQMediaMessageTests
- (void)setUp
{
[super setUp];
self.senderId = @"324543-43556-212343";
self.senderDisplayName = @"Jesse Squires";
self.date = [NSDate date];
self.mockMediaData = [OCMockObject mockForProtocol:@protocol(JSQMessageMediaData)];
}
- (void)tearDown
{
self.senderId = nil;
self.senderDisplayName = nil;
self.date = nil;
self.mockMediaData = nil;
[super tearDown];
}
- (void)testTextMessageInit
{
JSQMediaMessage *msg = [[JSQMediaMessage alloc] initWithSenderId:self.senderId
senderDisplayName:self.senderDisplayName
date:self.date
media:self.mockMediaData];
XCTAssertNotNil(msg, @"Message should not be nil");
}
- (void)testMessageInvalidInit
{
XCTAssertThrows([[JSQMediaMessage alloc] init], @"Invalid init should throw");
XCTAssertThrows([[JSQMediaMessage alloc] initWithSenderId:nil senderDisplayName:nil date:nil media:nil], @"Invalid init should throw");
}
- (void)testMessageIsEqual
{
JSQMediaMessage *msg = [[JSQMediaMessage alloc] initWithSenderId:self.senderId
senderDisplayName:self.senderDisplayName
date:self.date
media:self.mockMediaData];
JSQMediaMessage *copy = [msg copy];
XCTAssertEqualObjects(msg, copy, @"Copied messages should be equal");
XCTAssertEqual([msg hash], [copy hash], @"Copied messages hashes should be equal");
XCTAssertEqualObjects(msg, copy, @"Copied messages should be equal");
XCTAssertEqualObjects(msg, msg, @"Messages should be equal to itself");
}
- (void)testMessageArchiving
{
JSQMediaMessage *msg = [[JSQMediaMessage alloc] initWithSenderId:self.senderId
senderDisplayName:self.senderDisplayName
date:self.date
media:[FakeMedia new]];
NSData *msgData = [NSKeyedArchiver archivedDataWithRootObject:msg];
JSQMediaMessage *unarchivedMsg = [NSKeyedUnarchiver unarchiveObjectWithData:msgData];
XCTAssertEqualObjects(msg, unarchivedMsg, @"Message should be equal");
}
@end

50
JSQMessagesTests/ModelTests/JSQMessageTests.m Normal file → Executable file
View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,15 +8,16 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessage.h"
@interface JSQMessageTests : XCTestCase
@property (strong, nonatomic) NSString *senderId;
@property (strong, nonatomic) NSString *senderDisplayName;
@property (strong, nonatomic) NSString *text;
@property (strong, nonatomic) NSString *sender;
@property (strong, nonatomic) NSDate *date;
@end
@ -27,54 +28,63 @@
- (void)setUp
{
[super setUp];
self.senderId = @"324543-43556-212343";
self.senderDisplayName = @"Jesse Squires";
self.text = @"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque"
@"laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi"
@"architecto beatae vitae dicta sunt explicabo.";
self.sender = @"Jesse Squires";
self.date = [NSDate date];
}
- (void)tearDown
{
self.senderId = nil;
self.senderDisplayName = nil;
self.text = nil;
self.sender = nil;
self.date = nil;
[super tearDown];
}
- (void)testMessageInit
{
JSQMessage *msg = [[JSQMessage alloc] initWithSenderId:self.senderId senderDisplayName:self.senderDisplayName date:self.date isMedia:NO];
XCTAssertNotNil(msg, @"Message should not be nil");
JSQMessage *msg0 = [[JSQMessage alloc] initWithText:self.text sender:self.sender date:self.date];
XCTAssertNotNil(msg0, @"Message should not be nil");
JSQMessage *msg1 = [JSQMessage messageWithText:self.text sender:self.sender];
XCTAssertNotNil(msg1, @"Message shold not be nil");
}
- (void)testMessageInvalidInit
{
XCTAssertThrows([[JSQMessage alloc] init], @"Invalid init should throw");
XCTAssertThrows([[JSQMessage alloc] initWithSenderId:nil senderDisplayName:nil date:nil isMedia:NO], @"Invalid init should throw");
XCTAssertThrows([[JSQMessage alloc] initWithSenderId:self.senderId senderDisplayName:nil date:nil isMedia:YES], @"Invalid init should throw");
XCTAssertThrows([[JSQMessage alloc] initWithSenderId:nil senderDisplayName:self.senderDisplayName date:nil isMedia:NO], @"Invalid init should throw");
XCTAssertThrows([[JSQMessage alloc] initWithSenderId:nil senderDisplayName:nil date:self.date isMedia:YES], @"Invalid init should throw");
XCTAssertThrows([JSQMessage messageWithText:nil sender:nil], @"Invalid init should throw");
XCTAssertThrows([JSQMessage messageWithText:self.text sender:nil], @"Invalid init should throw");
XCTAssertThrows([JSQMessage messageWithText:nil sender:self.sender], @"Invalid init should throw");
XCTAssertThrows([[JSQMessage alloc] initWithText:nil sender:nil date:nil], @"Invalid init should throw");
XCTAssertThrows([[JSQMessage alloc] initWithText:self.text sender:nil date:nil], @"Invalid init should throw");
XCTAssertThrows([[JSQMessage alloc] initWithText:nil sender:self.sender date:nil], @"Invalid init should throw");
XCTAssertThrows([[JSQMessage alloc] initWithText:nil sender:nil date:self.date], @"Invalid init should throw");
}
- (void)testMessageIsEqual
{
JSQMessage *msg = [[JSQMessage alloc] initWithSenderId:self.senderId senderDisplayName:self.senderDisplayName date:self.date isMedia:NO];
JSQMessage *msg = [JSQMessage messageWithText:self.text sender:self.sender];
JSQMessage *copy = [msg copy];
XCTAssertEqualObjects(msg, copy, @"Copied messages should be equal");
XCTAssertEqual([msg hash], [copy hash], @"Copied messages hashes should be equal");
XCTAssertEqualObjects(msg, copy, @"Copied messages should be equal");
XCTAssertEqualObjects(msg, msg, @"Messages should be equal to itself");
XCTAssertTrue([msg isEqualToMessage:copy], @"Copied messages should be equal");
XCTAssertTrue([msg isEqualToMessage:msg], @"Messages should be equal to itself");
XCTAssertFalse([msg isEqualToMessage:nil], @"Initialized message should not be equal to nil");
}
- (void)testMessageArchiving
{
JSQMessage *msg = [[JSQMessage alloc] initWithSenderId:self.senderId senderDisplayName:self.senderDisplayName date:self.date isMedia:YES];
JSQMessage *msg = [JSQMessage messageWithText:self.text sender:self.sender];
NSData *msgData = [NSKeyedArchiver archivedDataWithRootObject:msg];
JSQMessage *unarchivedMsg = [NSKeyedUnarchiver unarchiveObjectWithData:msgData];
XCTAssertEqualObjects(msg, unarchivedMsg, @"Message should be equal");
XCTAssertTrue([msg isEqualToMessage:unarchivedMsg], @"Message should be equal");
}
@end

View File

@ -1,75 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// MIT License
// Copyright (c) 2014 Jesse Squires
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import "JSQMessagesAvatarImage.h"
@interface JSQMessagesAvatarImageTests : XCTestCase
@end
@implementation JSQMessagesAvatarImageTests
- (void)setUp
{
[super setUp];
}
- (void)tearDown
{
[super tearDown];
}
- (void)testInitInvalid
{
XCTAssertThrows([[JSQMessagesAvatarImage alloc] init], @"Invalid init should throw");
XCTAssertThrows([JSQMessagesAvatarImage avatarImageWithPlaceholder:nil], @"Invalid init should throw");
XCTAssertThrows([[JSQMessagesAvatarImage alloc] initWithAvatarImage:nil highlightedImage:nil placeholderImage:nil], @"Invalid init should throw");
}
- (void)testInitValid
{
UIImage *mockImage = [UIImage imageNamed:@"demo_avatar_jobs"];
JSQMessagesAvatarImage *avatar = [JSQMessagesAvatarImage avatarImageWithPlaceholder:mockImage];
XCTAssertNotNil(avatar, @"Valid init should succeed");
JSQMessagesAvatarImage *avatar2 = [JSQMessagesAvatarImage avatarWithImage:mockImage];
XCTAssertNotNil(avatar2, @"Valid init should succeed");
XCTAssertEqualObjects(avatar2.avatarImage, avatar2.avatarHighlightedImage);
XCTAssertEqualObjects(avatar2.avatarHighlightedImage, avatar2.avatarPlaceholderImage);
}
- (void)testCopy
{
UIImage *mockImage = [UIImage imageNamed:@"demo_avatar_jobs"];
JSQMessagesAvatarImage *avatar = [[JSQMessagesAvatarImage alloc] initWithAvatarImage:mockImage
highlightedImage:mockImage
placeholderImage:mockImage];
JSQMessagesAvatarImage *copy = [avatar copy];
XCTAssertNotNil(copy, @"Copy should succeed");
XCTAssertFalse(avatar == copy, @"Copy should return new, distinct instance");
XCTAssertNotEqualObjects(avatar.avatarImage, copy.avatarImage, @"Images should not be equal");
XCTAssertNotEqual(avatar.avatarImage, copy.avatarImage, @"Images should not be equal");
XCTAssertNotEqualObjects(avatar.avatarHighlightedImage, copy.avatarHighlightedImage, @"Images should not be equal");
XCTAssertNotEqual(avatar.avatarHighlightedImage, copy.avatarHighlightedImage, @"Images should not be equal");
XCTAssertNotEqualObjects(avatar.avatarPlaceholderImage, copy.avatarPlaceholderImage, @"Images should not be equal");
XCTAssertNotEqual(avatar.avatarPlaceholderImage, copy.avatarPlaceholderImage, @"Images should not be equal");
}
@end

View File

@ -1,63 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// MIT License
// Copyright (c) 2014 Jesse Squires
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import "JSQMessagesBubbleImage.h"
@interface JSQMessagesBubbleImageTests : XCTestCase
@end
@implementation JSQMessagesBubbleImageTests
- (void)setUp
{
[super setUp];
}
- (void)tearDown
{
[super tearDown];
}
- (void)testInitInvalid
{
XCTAssertThrows([[JSQMessagesBubbleImage alloc] init], @"Invalid init should throw");
XCTAssertThrows([[JSQMessagesBubbleImage alloc] initWithMessageBubbleImage:nil highlightedImage:nil], @"Invalid init should throw");
}
- (void)testInitValid
{
UIImage *mockImage = [UIImage imageNamed:@"bubble_min"];
JSQMessagesBubbleImage *bubbleImage = [[JSQMessagesBubbleImage alloc] initWithMessageBubbleImage:mockImage highlightedImage:mockImage];
XCTAssertNotNil(bubbleImage, @"Valid init should succeed");
}
- (void)testCopy
{
UIImage *mockImage = [UIImage imageNamed:@"bubble_min"];
JSQMessagesBubbleImage *bubbleImage = [[JSQMessagesBubbleImage alloc] initWithMessageBubbleImage:mockImage highlightedImage:mockImage];
JSQMessagesBubbleImage *copy = [bubbleImage copy];
XCTAssertNotNil(copy, @"Copy should succeed");
XCTAssertFalse(bubbleImage == copy, @"Copy should return new, distinct instance");
XCTAssertNotEqualObjects(bubbleImage.messageBubbleImage, copy.messageBubbleImage, @"Images should not be equal");
XCTAssertNotEqual(bubbleImage.messageBubbleImage, copy.messageBubbleImage, @"Images should not be equal");
XCTAssertNotEqualObjects(bubbleImage.messageBubbleHighlightedImage, copy.messageBubbleHighlightedImage, @"Images should not be equal");
XCTAssertNotEqual(bubbleImage.messageBubbleHighlightedImage, copy.messageBubbleHighlightedImage, @"Images should not be equal");
}
@end

View File

@ -1,91 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// MIT License
// Copyright (c) 2014 Jesse Squires
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import "JSQTextMessage.h"
@interface JSQTextMessageTests : XCTestCase
@property (strong, nonatomic) NSString *senderId;
@property (strong, nonatomic) NSString *senderDisplayName;
@property (strong, nonatomic) NSDate *date;
@property (strong, nonatomic) NSString *text;
@end
@implementation JSQTextMessageTests
- (void)setUp
{
[super setUp];
self.senderId = @"324543-43556-212343";
self.senderDisplayName = @"Jesse Squires";
self.date = [NSDate date];
self.text = @"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque"
@"laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi"
@"architecto beatae vitae dicta sunt explicabo.";
}
- (void)tearDown
{
self.senderId = nil;
self.senderDisplayName = nil;
self.date = nil;
self.text = nil;
[super tearDown];
}
- (void)testTextMessageInit
{
JSQTextMessage *msg = [[JSQTextMessage alloc] initWithSenderId:self.senderId
senderDisplayName:self.senderDisplayName
date:self.date
text:self.text];
XCTAssertNotNil(msg, @"Message should not be nil");
}
- (void)testMessageInvalidInit
{
XCTAssertThrows([[JSQTextMessage alloc] init], @"Invalid init should throw");
XCTAssertThrows([[JSQTextMessage alloc] initWithSenderId:nil senderDisplayName:nil date:nil text:nil], @"Invalid init should throw");
}
- (void)testMessageIsEqual
{
JSQTextMessage *msg = [[JSQTextMessage alloc] initWithSenderId:self.senderId
senderDisplayName:self.senderDisplayName
date:self.date
text:self.text];
JSQTextMessage *copy = [msg copy];
XCTAssertEqualObjects(msg, copy, @"Copied messages should be equal");
XCTAssertEqual([msg hash], [copy hash], @"Copied messages hashes should be equal");
XCTAssertEqualObjects(msg, copy, @"Copied messages should be equal");
XCTAssertEqualObjects(msg, msg, @"Messages should be equal to itself");
}
- (void)testMessageArchiving
{
JSQTextMessage *msg = [[JSQTextMessage alloc] initWithSenderId:self.senderId
senderDisplayName:self.senderDisplayName
date:self.date
text:self.text];
NSData *msgData = [NSKeyedArchiver archivedDataWithRootObject:msg];
JSQTextMessage *unarchivedMsg = [NSKeyedUnarchiver unarchiveObjectWithData:msgData];
XCTAssertEqualObjects(msg, unarchivedMsg, @"Message should be equal");
}
@end

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesCollectionViewCellIncoming.h"
#import "JSQMessagesCollectionViewCellOutgoing.h"
@ -30,24 +31,19 @@
[super tearDown];
}
- (void)testMessagesIncomingCollectionViewCellInit
- (void)testMessagesCollectionViewCellInit
{
UINib *incomingCell = [JSQMessagesCollectionViewCellIncoming nib];
XCTAssertNotNil(incomingCell, @"Nib should not be nil");
NSString *incomingCellId = [JSQMessagesCollectionViewCellIncoming cellReuseIdentifier];
XCTAssertNotNil(incomingCellId, @"Cell identifier should not be nil");
XCTAssertEqualObjects(incomingCellId, NSStringFromClass([JSQMessagesCollectionViewCellIncoming class]));
}
- (void)testMessagesOutgoingCollectionViewCellInit
{
UINib *outgoingCell = [JSQMessagesCollectionViewCellOutgoing nib];
XCTAssertNotNil(outgoingCell, @"Nib should not be nil");
NSString *outgoingCellId = [JSQMessagesCollectionViewCellOutgoing cellReuseIdentifier];
XCTAssertNotNil(outgoingCellId, @"Cell identifier should not be nil");
XCTAssertEqualObjects(outgoingCellId, NSStringFromClass([JSQMessagesCollectionViewCellOutgoing class]));
}
@end

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesCollectionView.h"
#import "JSQMessagesCollectionViewFlowLayout.h"

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesComposerTextView.h"

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesViewController.h"
#import "JSQMessagesInputToolbar.h"

5
JSQMessagesTests/ViewTests/JSQMessagesLabelTests.m Normal file → Executable file
View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesLabel.h"

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesLoadEarlierHeaderView.h"

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesToolbarContentView.h"
#import "JSQMessagesComposerTextView.h"

View File

@ -1,6 +1,6 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
// http://www.hexedbits.com
//
//
// MIT License
@ -8,7 +8,8 @@
// http://opensource.org/licenses/MIT
//
@import XCTest;
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesTypingIndicatorFooterView.h"

View File

@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

6
JSQMessagesViewController.podspec Normal file → Executable file
View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'JSQMessagesViewController'
s.version = '6.0-beta5'
s.version = '5.3.2'
s.summary = 'An elegant messages UI library for iOS.'
s.homepage = 'http://jessesquires.github.io/JSQMessagesViewController'
s.license = 'MIT'
@ -12,8 +12,8 @@ Pod::Spec.new do |s|
s.platform = :ios, '7.0'
s.source_files = 'JSQMessagesViewController/**/*.{h,m}'
s.resources = 'JSQMessagesViewController/Assets/**/*.{png,aiff}', 'JSQMessagesViewController/**/*.{xib}'
s.frameworks = 'QuartzCore', 'CoreGraphics', 'CoreLocation', 'MapKit', 'UIKit', 'Foundation'
s.frameworks = 'QuartzCore', 'CoreGraphics'
s.requires_arc = true
s.dependency 'JSQSystemSoundPlayer', '~> 2.0.0'
s.dependency 'JSQSystemSoundPlayer', '1.5.2'
end

Some files were not shown because too many files have changed in this diff Show More