Compare commits

..

54 Commits

Author SHA1 Message Date
Christine Corbett
26fb5cbcf4 groups and calls have optional avatar; consumer must specify that it should be used and provide images in project of naming convention. otherwise no image will be used 2015-01-27 22:53:25 -10:00
Christine Corbett
c8262eee36 calls and group update messages now blue styled in correct font 2015-01-25 19:10:42 -10:00
Joyce Yan
184f53b07b Design tweaks based on @abolishme's work. 2015-01-24 08:31:23 -10:00
dtsbourg
ed9858bd6d revert b73b5d 2014-12-29 23:48:01 +01:00
dtsbourg
9dffc05aa7 Merge branch 'FredericJacobs-JSignalQ' into JSignalQ 2014-12-29 22:07:24 +01:00
Frederic Jacobs
cb5c4facbc Removing unused properties + bug fix call label 2014-12-29 21:56:58 +01:00
dtsbourg
84d1b659f3 Typo fix 2014-12-29 21:21:19 +01:00
dtsbourg
b73b5d9983 Performance enhancement for collection view reloading 2014-12-29 19:25:29 +01:00
dtsbourg
6a30411791 Merge remote-tracking branch 'jsq/master' into JSignalQ-6.1.1 2014-12-23 18:04:39 +01:00
dtsbourg
8703ce020c JSQDisplayedMessage: implement tap delegate 2014-12-10 21:45:29 +01:00
dtsbourg
fcbbfdc43f Fix crash on long tap on error and info messages 2014-12-09 22:37:56 +01:00
dtsbourg
bc976a04d9 Cells: change isKindOfClass to messageType check 2014-12-07 14:42:27 +01:00
dtsbourg
43f6e75bbf Set adapter type as property 2014-12-06 18:23:03 +01:00
dtsbourg
59ea2b6920 Revert to TSMessageAdapterType for naming to avoid conflicts 2014-12-06 16:57:31 +01:00
dtsbourg
dee758a3ff TSMessageType added to JSQMessageData 2014-12-06 16:52:16 +01:00
dtsbourg
82482a1fc5 Remove call button on toolbar 2014-12-04 16:11:34 +01:00
dtsbourg
7c2cec63f9 Remove unnecessary res 2014-11-30 19:55:56 +01:00
dtsbourg
91fbb4dce7 JSQDisplayedMessage: Update UI 2014-11-30 19:55:27 +01:00
dtsbourg
0d8fabe142 Calls: Update UI 2014-11-30 16:51:24 +01:00
dtsbourg
4049f54789 JSQDisplayedMessage: Link to UI 2014-11-29 15:30:53 +01:00
dtsbourg
54ae40b07a JSQDisplayedMessageCollectionViewCell: Base class 2014-11-29 15:06:43 +01:00
dtsbourg
bcf0ac6e1f JSQErrorMessage: Model 2014-11-29 14:48:59 +01:00
dtsbourg
e70cec697f JSQDisplayedMessage: Model + JSQInfoMessage: Model 2014-11-29 14:39:59 +01:00
dtsbourg
b22b7a4caf JSQMessagesBubbleImageFactory: Add a failed message bubble 2014-11-27 12:43:24 +01:00
dtsbourg
b8b3fb9122 JSQMessageData: add message status field 2014-11-27 12:29:49 +01:00
dtsbourg
5fc12f5cba Merge branch 'master' of https://github.com/jessesquires/JSQMessagesViewController into JSignalQ 2014-11-26 18:04:32 +01:00
dtsbourg
4cad607ae2 none 2014-11-26 18:01:19 +01:00
dtsbourg
597670e446 JSQCallCollectionViewCell: UI 2014-11-21 23:01:16 +01:00
dtsbourg
881ddddeb4 Demo: make JSQM6.0 work with JSQCall 2014-11-21 22:14:53 +01:00
dtsbourg
32395453ff Finish merging 2014-11-21 13:43:21 +01:00
dtsbourg
5c6dce5a04 Fix merge from master conflicts 2014-11-21 13:37:28 +01:00
dtsbourg
3d248e4af0 JSQCall : layout 2014-11-21 12:02:20 +01:00
dtsbourg
6bbef1949b JSQCall model 2014-11-20 14:57:18 +01:00
dtsbourg
1031a89858 JSQMessage: Add failed state 2014-11-20 10:10:55 +01:00
dtsbourg
21d877492e InputToolbar: blue BarButtonItems 2014-11-19 13:05:35 +01:00
dtsbourg
5670accd2c General: Font update 2014-11-18 18:05:24 +01:00
dtsbourg
d138d4f3a3 InputToolbar: Fine tune enabling on rightBarButtonItem 2014-11-17 20:41:08 +01:00
dtsbourg
cddbbf2c75 InputToolbar: Bar button item always responds to tap events 2014-11-17 20:27:57 +01:00
dtsbourg
104ba0e023 MessageStatus: add kMessageNone status 2014-11-17 20:22:59 +01:00
dtsbourg
a27fa1091e Test: Custom UIButton in factory 2014-11-17 20:17:08 +01:00
dtsbourg
7446b63cbb remove * 2014-11-12 22:31:22 +01:00
dtsbourg
73482f6ace ≈Merge branch 'issue_492_scrollviewperformance' into JSignalQ 2014-11-12 22:26:40 +01:00
dtsbourg
2dad6e3036 add message status 2014-11-12 22:22:59 +01:00
dtsbourg
99971a8d38 Merge branch 'JSignalQ' of https://github.com/dtsbourg/JSQMessagesViewController into JSignalQ 2014-10-28 23:39:44 +01:00
dtsbourg
da7203dee2 [UIColor whiteColor] 2014-10-28 23:37:11 +01:00
dtsbourg
88e16ac830 white bg ? 2014-10-28 23:37:11 +01:00
dtsbourg
41dddfea3a cell xib white bg 2014-10-28 23:37:11 +01:00
dtsbourg
ebea4ef0b8 Restore white bg 2014-10-28 23:37:11 +01:00
dtsbourg
f115194efa Signal 2014-10-28 23:37:11 +01:00
dtsbourg
06e7c2bec9 [UIColor whiteColor] 2014-10-28 22:51:14 +01:00
dtsbourg
6dded2cce9 white bg ? 2014-10-28 22:28:47 +01:00
dtsbourg
f03bac13a0 cell xib white bg 2014-10-28 22:23:39 +01:00
dtsbourg
33b81ca6b0 Restore white bg 2014-10-28 22:19:28 +01:00
dtsbourg
752edc4f0f Signal 2014-10-28 21:49:55 +01:00
225 changed files with 2822 additions and 7414 deletions

View File

@ -1,34 +0,0 @@
codecov:
branch: develop
coverage:
precision: 2
round: nearest
range: "60...100"
ignore:
- JSQMessagesDemo/*
- Pods/*
- JSQMessagesTests/*
status:
project:
default:
target: auto
threshold: 2.0
branches:
- master
- develop
patch:
default:
target: auto
branches:
- master
- develop
comment:
layout: "header, diff, changes, sunburst, uncovered"
branches:
- master
- develop
behavior: default

74
.github/CONDUCT.md vendored
View File

@ -1,74 +0,0 @@
# JSQMessagesViewController Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at **jesse.squires.developer [at] gmail [dot] com**. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@ -1,51 +0,0 @@
# Contributing to JSQMessagesViewController
## Code of Conduct
Please read our [Code of Conduct](https://github.com/jessesquires/JSQMessagesViewController/blob/develop/.github/CONDUCT.md). Intolerance, disrespect, and any of form of negativity will not be tolerated.
## Opening a new issue
1. Read *all* of the [`README`](https://github.com/jessesquires/JSQMessagesViewController/blob/develop/README.md) :speak_no_evil:
* Search [open issues](https://github.com/jessesquires/JSQMessagesViewController/issues) *and* [closed issues](https://github.com/jessesquires/JSQMessagesViewController/issues?q=is%3Aissue+is%3Aclosed) to **avoid opening a duplicate issue!** :see_no_evil:
* If your issue exists, please comment on its thread with your new information :hear_no_evil:
* Otherwise, open a new issue with a good title and description :memo:
* Provide **all** of the following information:
- Library version(s) :octocat:
- iOS version(s) :iphone:
- Devices/Simulators affected :iphone:
- Expected behavior vs actual behavior
- Complete steps to reproduce the issue :warning:
- Link to a project that exhibits the issue, if possible fork the repo and modify the provided demo project :construction:
- Screenshots/GIFs/Videos showing the issue, if applicable :camera:
- Full crash log, if applicable :boom:
- Search for and list any issues that might be related :mag_right:
## Submitting a pull request
1. Link to the issue that the pull request resolves. If there isn't one, create one.
2. Write unit tests that test your changes, if applicable.
3. Update header docs, if needed.
4. Follow existing coding style, and these [style guidelines](https://github.com/jessesquires/HowToContribute#style-guidelines).
5. Resolve any merge conflicts.
6. Squash your commits into a single commit.
## Questions and help
See the [Questions & Help](https://github.com/jessesquires/JSQMessagesViewController/blob/develop/README.md#questions--help), and [Documentation](https://github.com/jessesquires/JSQMessagesViewController/blob/develop/README.md#documentation) sections in the `README`.
## General guidelines
Please also read through these more general [contribution guidelines](https://github.com/jessesquires/HowToContribute).
## Did you read all of this?
You even followed the links? Congratulations! You deserve a high-five. :tada:
![img](http://media.giphy.com/media/LdnaND03GRE9q/giphy.gif)
### New issue checklist
Now show me how awesome you are! :smile: When opening your new issue and filling out the checklist, you'll be asked for confirmation. Confirm that you've read this with these emoji: :muscle::sunglasses::facepunch:
> - [x] I have reviewed the contributing guidelines. Confirmation: :muscle::sunglasses::facepunch:

View File

@ -1,36 +0,0 @@
## New issue checklist
<!-- Before submitting this issue, make sure you have done the following -->
- [ ] I have read all of the [`README`](https://github.com/jessesquires/JSQMessagesViewController/blob/develop/README.md), [documentation](http://cocoadocs.org/docsets/JSQMessagesViewController/), and [FAQ](https://github.com/jessesquires/JSQMessagesViewController/blob/develop/Documentation/faq.md).
- [ ] I have reviewed the [contributing guidelines](https://github.com/jessesquires/JSQMessagesViewController/blob/develop/.github/CONTRIBUTING.md). Confirmation: ____
- [ ] I have searched [existing issues](https://github.com/jessesquires/JSQMessagesViewController/issues?q=is%3Aissue+sort%3Acreated-desc) and **this is not a duplicate**.
### General information
- Library version(s):
- iOS version(s):
- Devices/Simulators affected:
- Reproducible in the demo project? (Yes/No):
- Related issues:
## Bug report
#### Expected behavior
> ...
#### Actual behavior
> ...
#### Steps to reproduce
> ...
#### Crash log? Screenshots? Videos? Sample project?
>...
## Question or Feature Request
> ...

View File

@ -1,11 +0,0 @@
## Pull request checklist
- [ ] All tests pass. Demo project builds and runs.
- [ ] I have resolved any merge conflicts.
- [ ] I have followed the [coding style](https://github.com/jessesquires/HowToContribute#style-guidelines), and reviewed the [contributing guidelines](https://github.com/jessesquires/JSQMessagesViewController/blob/develop/.github/CONTRIBUTING.md). Confirmation: ____
#### This fixes issue #___.
## What's in this pull request?
>...

9
.gitignore vendored
View File

@ -1,6 +1,6 @@
.DS_Store
# Xcode
.DS_Store
/build/*
*/build/*
*.pbxuser
@ -18,3 +18,8 @@ DerivedData
.idea/
*.hmap
*.xccheckout
#CocoaPods
Pods

View File

@ -1,44 +1,10 @@
language: objective-c
osx_image: xcode7.3
env:
global:
- LANG=en_US.UTF-8
- WORKSPACE="JSQMessages.xcworkspace"
- IOS_SCHEME="JSQMessages"
- IOS_SDK=iphonesimulator9.3
before_install:
- export LANG=en_US.UTF-8
- gem install cocoapods
- brew update
- if brew outdated | grep -qx xctool; then brew upgrade xctool; fi
matrix:
- DESTINATION="OS=8.1,name=iPhone 5" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO" COVERAGE="NO"
- DESTINATION="OS=9.0,name=iPhone 6 Plus" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="NO" BUILD_EXAMPLE="NO" POD_LINT="YES" COVERAGE="YES"
before_install:
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet
# skip pod install on travis-ci
# since we check-in the pods folder, etc. this isn't needed
install: true
script:
- if [ $POD_LINT == "YES" ]; then
pod spec lint;
pod lib lint;
fi
- if [ $RUN_TESTS == "YES" ]; then
xcodebuild clean build test -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO | xcpretty -c;
else
xcodebuild clean build -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO | xcpretty -c;
fi
# Build for reporting test coverage
- if [ $COVERAGE == "YES" ]; then
xcodebuild clean build test -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES;
fi
after_success:
- if [ $COVERAGE == "YES" ]; then
bash <(curl -s https://codecov.io/bash);
fi
script:
- xctool clean build test -workspace JSQMessages.xcworkspace -scheme JSQMessages -sdk iphonesimulator7.1 ONLY_ACTIVE_ARCH=NO

View File

@ -1,125 +0,0 @@
# CHANGELOG
The changelog for `JSQMessagesViewController`. Also see the [releases](https://github.com/jessesquires/JSQMessagesViewController/releases) on GitHub.
--------------------------------------
7.3.4
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A7.3.4+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/7.3.4)
7.3.3
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A7.3.3+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/7.3.3)
7.3.2
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A7.3.2+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/7.3.2)
7.3.1
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A7.3.1+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/7.3.1)
7.3.0
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A7.3.0+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/7.3.0)
7.2.0
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A7.2.0+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/7.2.0)
7.1.0
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A7.1.0+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/7.1.0)
7.0.2
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A7.0.2+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/7.0.2)
7.0.1
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A7.0.1+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/7.0.1)
7.0.0
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A7.0.0+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/7.0.0)
6.1.3
-----
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/6.1.3)
6.1.2
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A6.1.2+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/6.1.2)
6.1.1
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A6.1.1+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/6.1.1)
6.0.0
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A6.0.0+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/6.0.0)
5.3.0
-----
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/5.3.0)
5.2.0
-----
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/5.2.0)
5.1.0
-----
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/5.1.0)
5.0.3
-----
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/5.0.3)
5.0.0
-----
- [Milestone](https://github.com/jessesquires/JSQMessagesViewController/issues?q=milestone%3A5.0.0+is%3Aclosed)
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/5.0.0)
4.0.0
-----
- [GitHub release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/4.0.0)
All previous versions
---------------------
Unfortunately, release notes are not available for earlier versions of the library.

3
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,3 @@
## How To Contribute
Please follow these sweet [contribution guidelines](https://github.com/jessesquires/HowToContribute).

View File

@ -1,46 +0,0 @@
# Apps using this library
These are the (known) apps that use `JSQMessagesViewController`. Submit a [pull request](https://github.com/jessesquires/JSQMessagesViewController/compare) to join the list! :smile:
-----------------
* [Hemoglobe](http://bit.ly/hemoglobeapp)
* [PocketSuite](https://itunes.apple.com/us/app/pocketsuite/id721795146)
* [FireChat](https://itunes.apple.com/us/app/firechat/id719829352)
* [Signal](https://github.com/WhisperSystems/Signal-iOS)
* [ClassDojo](https://itunes.apple.com/us/app/classdojo/id552602056)
* [Schools App](https://itunes.apple.com/us/app/schools-app/id495845755)
* [ChatSecure](https://chatsecure.org)
* [Bryx 911](https://itunes.apple.com/us/app/bryx-911/id813078029)
* [Kytt](https://itunes.apple.com/de/app/kytt-neue-leute-in-der-umgebung/id848959696)
* [Spark Social](https://itunes.apple.com/us/app/spark-social/id823785892)
* [Spabbit](https://itunes.apple.com/us/app/spabbit/id737363908)
* [Elodie](https://itunes.apple.com/app/elodie/id821610181)
* [Instaply](https://itunes.apple.com/us/app/instaply/id558562920)
* [Loopse](https://itunes.apple.com/us/app/loopse-spots-friends-sessions/id704783915)
* [Oxwall Messenger](https://github.com/tochman/OxwallMessenger)
* [FourChat](https://itunes.apple.com/us/app/fourchat/id650833730)
* [vCinity](https://itunes.apple.com/us/app/vcinity-chat-without-internet/id875395391)
* [Quick Text Message](https://itunes.apple.com/us/app/quick-text-message-fast-sms/id583729997)
* [Libraries for developers](https://itunes.apple.com/us/app/libraries-for-developers/id653427112)
* [Buhz|Hyve](https://itunes.apple.com/us/app/buhz-hyve/id818568956)
* [Ringring.io](https://github.com/ringring-io/ringring-ios)
* [gDecide](https://itunes.apple.com/ca/app/gdecide/id716801285)
* [AwesomeChat](https://github.com/relatedcode/RealtimeChat)
* [ParseChat](https://github.com/relatedcode/ParseChat)
* [Jib](http://jibapp.com)
* [Onvolo](https://itunes.apple.com/us/app/onvolo/id869332351)
* [EVCloudKitDao](https://github.com/evermeer/EVCloudKitDao)
* [Fluky Chat](https://itunes.apple.com/us/app/fluky-chat-secure-anonymous/id958605886)
* [VillageUnity](https://itunes.apple.com/us/app/village-unity/id919972368)
* [Pine](https://itunes.apple.com/us/app/pine-innovation-product-life/id946589228)
* [NotificationChat](https://github.com/relatedcode/EncryptedChat)
* [RealtimeChat](https://github.com/relatedcode/RealtimeChat)
* [Bazar](https://itunes.apple.com/ru/app/bazar-talk-about-everything/id885453058)
* [Roomie](https://itunes.apple.com/us/app/roomie-find-your-roomie/id962585201)
* [PimpMyCall](https://itunes.apple.com/us/app/pimp-my-call/id990167537)
* [Yellow Partner](https://itunes.apple.com/us/app/yellow-partner/id1062994361?ls=1&mt=8)
* [Radiate](https://itunes.apple.com/us/app/radiate/id939284774?mt=8)
* [Criptext](https://itunes.apple.com/us/app/criptext-secure-messenger/id848647361?mt=8)
* [multipeer-chat](https://github.com/J4awesome/multipeer-chat)
* *Your app here, submit a [pull request](https://github.com/jessesquires/JSQMessagesViewController/compare)!*

View File

@ -1,130 +0,0 @@
# Contributor Onboarding
*Contributor onboarding guide for JSQMessagesViewController*
This guide is intended to bring new core contributors up-to-speed on the project, organization, expectations, and best practices.
-------------------------
## Introduction
Welcome! :smile: If you are reading this, then you are (or are about to be) a core contributor! :tada: The goal of this document is to cover everything you need to know about helping to maintain this project. If you are not familiar with the code, the docs, the demo project, and everything else in the repo, then that should be your first step. Otherwise, continue on!
## Getting push access
Being a **contributor** means submitting pull requests, opening issues, etc. Being a **core contributor** means getting push access and other permissions.
We love freely giving push access to great contributors, and always err on trusting contributors with this responsibility. However, before granting you push access we would like to see a few things:
- An interest and dedication to the project
- Helping to triage issues, review pull requests, and diagnose bugs
- Submitting a couple great pull requests
We really prefer to grant push access to contributors who have a decent amount of time to share each week or month. If you cannot be extremely active on the project — that's ok! You can still be an :sparkles: awesome contributor :sparkles: without getting push access!
The rationale behind all of this is that we do not want to accumulate a *huge* list of **core contributors** that are *not* regularly active.
Remember, *your time* is *your time* — there is absolutely no pressure on you to spend a lot of time on this project, although it is greatly appreciated! :smile:
> **Note:** the rest of this document applies to both **contributors** and **core contributors**, but there are some details that would require having push access.
## Core team
### Project lead
Jesse Squires ([**@jessesquires**](https://github.com/jessesquires)) serves as the lead for `JSQMessagesViewController`.
Responsibilities include:
- Managing releases and CocoaPods distributions
- Merging code into `master`
- Overall guidance on design, architecture, and implementation
- Strategic direction for the library
- Onboarding new core contributors
- Everything under **Core Contributors** :smile:
- Anything not covered by **Core Contributors** :smile:
As core contributors grow and take on more repsonsibility, they can become a lead.
### Core contributors
Core contributors have push access and are responsible for:
- Bug fixes
- New features
- Triaging issues (managing, organizing)
- Reviewing pull requests
- Answering questions from the community on [issues](https://github.com/jessesquires/JSQMessagesViewController/issues?utf8=✓&q=is%3Aissue+label%3A%22questions+%26+help%22+) and [StackOverflow](http://stackoverflow.com/questions/tagged/jsqmessagesviewcontroller)
- Documentation
Current core contributors:
- Harlan Haskans ([**@harlanhaskins**](https://github.com/harlanhaskins))
- Eli Burke ([**@eliburke**](https://github.com/eliburke))
## Pushing code
Although you have permissions to push code directly to `develop` as a core contributor, we ask that you *always* submit a pull request for code changes. After a code review and approval, you may merge your diff. For minor changes, like formatting or typos, pushing directly to `develop` is acceptable.
Always merge work to `develop` unless otherwise specified. The project lead will manage the `master` branch.
For now, Jesse ([**@jessesquires**](https://github.com/jessesquires)) should provide the final approval for *all* pull requests. However, as core contributors grow and establish themselves in the project, they can take on this responsibility as well.
## Project managment
### General guidelines
Above all, abide by our [code of conduct](https://github.com/jessesquires/JSQMessagesViewController/blob/develop/.github/CONDUCT.md) at all times. Be welcoming, kind, and inclusive.
Often, users do not follow our [contributing guidelines](https://github.com/jessesquires/JSQMessagesViewController/blob/develop/.github/CONTRIBUTING.md), fail to complete the [issue template](https://github.com/jessesquires/JSQMessagesViewController/blob/develop/.github/ISSUE_TEMPLATE.md), or fail to complete the [pull request template](https://github.com/jessesquires/JSQMessagesViewController/blob/develop/.github/PULL_REQUEST_TEMPLATE.md). This is frustrating, but the best response is to kindly remind and encourage them to follow the correct procedures next time.
When first responding to a newly opened issue or pull request, *always* thank the contributor and add some sweet emoji. Any positive emoji will work. (:+1:, :smile:, :sunglasses:, etc.) Choose your favorite.
> Thanks **@jessesquires**! :smile_cat:
Then continue on with the rest of your comment. There will be times where we simply cannot accept a patch for various reasons. In this case, kindly explain why it is not the right approach for the library, thank them for their time and effort, and encourage them to keep contributing.
In any situation, when in doubt, tag the project lead in a comment to get feedback.
### Development
- All work for minor and patch releases should happen on `develop`. For example, release 7.x.x.
- All work for major releases should happen on a release branch. For example, `release_8.0`.
- The project lead will manage the `master` branch.
For core contributors, always assign issues or pull requests to the appropriate team member. If you are working on an issue, assign it to yourself. If you would like someone to review a pull request, assign it to them.
### Managing issues
- Always add the appropriate label(s). There may be more than one.
- Assign to a release milestone, if applicable.
- Ask for more information from the user, if needed.
- Verify bugs. Leave comments on your findings as necessary.
- If it's a duplicate, label and close.
- Follow the general guidelines above.
##### Special labels
- [`needs review`](https://github.com/jessesquires/JSQMessagesViewController/issues?q=is%3Aissue+label%3A%22needs+review%22): These issues need to be triaged and confirmed. They are typically bugs or pull requests, but do not have to be. Once verified, `needs review` should be removed and any other appropriate labels should be added.
- [`new release roadmap`](https://github.com/jessesquires/JSQMessagesViewController/issues?utf8=✓&q=is%3Aissue+label%3A%22new+release+roadmap%22+): For communicating new releases to the community.
- [`in-progress`](https://github.com/jessesquires/JSQMessagesViewController/issues?q=is%3Aissue+label%3Ain-progress): Specifies a task that is currently being worked on. Remove this label after closing a task.
- [`duplicate`](https://github.com/jessesquires/JSQMessagesViewController/issues?utf8=✓&q=label%3Aduplicate+): For duplicate isses. When closing an issue as a duplicate be sure to leave a comment with the original issue number. *"Closing as duplicate of #6."*
- [`questions & help`](https://github.com/jessesquires/JSQMessagesViewController/issues?q=is%3Aissue+label%3A%22questions+%26+help%22): For community questions and help. Note that we are trying to refer questions to [StackOverflow](http://stackoverflow.com/questions/tagged/jsqmessagesviewcontroller) instead.
### Managing pull requests
- Review the code for correctness, performance, style, etc. Leave comments as needed.
- Always add the appropriate label(s). There may be more than one.
- Assign to a release milestone, if applicable.
- Follow the general guidelines above.
- If you think it's ready to go, tag the project lead to get the final :+1:
### Managing releases
All releases are organized using [milestones](https://github.com/jessesquires/JSQMessagesViewController/milestones). Use these to prioritize work and figure out what's next.
Issues and pull requests included in the next milestone release should be the highest priorty. Once a milestone is 100% complete, the project lead will merge `develop` or other release branches into `master`. The project lead will close the milestone, tag the release, and submit to CocoaPods.
### Managing documentation
Having high quality documentation and 100% coverage has a significant impact on the project's success.
Always add new docs for new public APIs and keep them up-to-date. Use existing docs and Apple's docs for Cocoa as guidelines for writing great documentation.

View File

@ -1,109 +0,0 @@
# FAQ
*Frequently asked questions for JSQMessagesViewController.*
Contributions are welcome! Please submit a [pull request](https://github.com/jessesquires/JSQMessagesViewController/compare).
------------------------------------
## For 7.x.x
#### Using `UITabBar` ?
Is the library compatible with `UITabBarController` and `UITabBar`? Yes and no. For the history on this issue, see [#179](https://github.com/jessesquires/JSQMessagesViewController/issues/179) and [#94](https://github.com/jessesquires/JSQMessagesViewController/issues/94). This seems to be the best workaround:
````objective-c
- (void)viewDidLoad
{
[super viewDidLoad];
self.edgesForExtendedLayout = UIRectEdgeNone;
}
````
#### *Springy bubbles?*
:warning: Note: this feature is still experimental.
````objective-c
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.collectionView.collectionViewLayout.springinessEnabled = YES;
}
````
#### *Remove avatars?*
````objective-c
- (void)viewDidLoad
{
[super viewDidLoad];
self.collectionView.collectionViewLayout.incomingAvatarViewSize = CGSizeZero;
self.collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero;
}
- (id<JSQMessageAvatarImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView avatarImageDataForItemAtIndexPath:(NSIndexPath *)indexPath
{
return nil;
}
````
#### *Need customize your collection view cells?*
There are 2 approaches to this, which one you choose depends on your needs.
1. Customize appearance and behavior of existing cells. (Easy)
2. Provide your own completely custom cell prototypes. (Hard)
> Also see [previous issues](https://github.com/jessesquires/JSQMessagesViewController/issues?utf8=✓&q=custom+cell+in%3Atitle).
##### (1) Customizing existing cells
If you only need to make minor changes to the existing cells (colors, data detectors, etc.), then you simply need to override the following method. You have access to all properties on the cell. ([docs](http://cocoadocs.org/docsets/JSQMessagesViewController/7.2.0/Classes/JSQMessagesCollectionViewCell.html))
````objective-c
- (UICollectionViewCell *)collectionView:(JSQMessagesCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
// Customize the shit out of this cell
// See the docs for JSQMessagesCollectionViewCell
return cell;
}
````
##### (2) Providing your own cell prototypes
This approach is more involved, but gives you greater flexibility. If you need to add or modify subviews of the cell, use this approach. ([docs](http://cocoadocs.org/docsets/JSQMessagesViewController/7.2.0/Classes/JSQMessagesViewController.html))
1. You need to provide your own cell subclasses, similar to the library's `JSQMessagesCollectionViewCell`, `JSQMessagesCollectionViewCellIncoming`, `JSQMessagesCollectionViewCellOutgoing`.
2. On your `JSQMessagesViewController` subclass, set the following properties according to your classes:
- `outgoingCellIdentifier`
- `outgoingMediaCellIdentifier`
- `incomingCellIdentifier`
- `incomingMediaCellIdentifier`
3. Register your cell classes/nibs with the collection view and the identifiers above
4. Override `-collectionView: cellForItemAtIndexPath:`. Do not call `super`. Since you are providing your own cells, calling `super` will perform a bunch of unnecessary work.
5. (Optional) For your model objects, implement `JSQMessageData` or subclass `JSQMessage` and extend to your needs.
#### *Customize your toolbar buttons?*
````objective-c
- (void)viewDidLoad
{
[super viewDidLoad];
// This button will call the `didPressAccessoryButton:` selector on your JSQMessagesViewController subclass
self.inputToolbar.contentView.leftBarButtonItem = /* custom button or nil to remove */
// This button will call the `didPressSendButton:` selector on your JSQMessagesViewController subclass
self.inputToolbar.contentView.rightBarButtonItem = /* custom button or nil to remove */
// Swap buttons, move send button to the LEFT side and the attachment button to the RIGHT
// For RTL language support
self.inputToolbar.contentView.leftBarButtonItem = [JSQMessagesToolbarButtonFactory defaultSendButtonItem];
self.inputToolbar.contentView.rightBarButtonItem = [JSQMessagesToolbarButtonFactory defaultAccessoryButtonItem];
// The library will call the correct selector for each button, based on this value
self.inputToolbar.sendButtonOnRight = NO;
}
````

View File

@ -1,56 +0,0 @@
# Getting Started
*Getting started guide for JSQMessagesViewController*
-----------------------------
## For versions 6.x and 7.x
````objective-c
#import <JSQMessagesViewController/JSQMessages.h> // import all the things
````
* **Tutorials and blogs**
* Read the [blog post](http://www.jessesquires.com/introducing-jsqmessagesvc-6-0/) about the 6.0 release!
* Ray Wenderlich has a [great tutorial](http://www.raywenderlich.com/122148/firebase-tutorial-real-time-chat), written by [David East](https://twitter.com/_davideast). (For 7.x releases)
* **Demo Project**
* There's a sweet demo project: `JSQMessages.xcworkspace`.
* Run `pod install` first.
* Swift Example can be found in the SwiftExample folder just open the `SwiftExample.xcworkspace`.
* Run `pod install` first.
* [Firebase](https://www.firebase.com) also has a sweet [demo project](https://github.com/firebase/ios-swift-chat-example), and it's in Swift!
* **Message Model**
* Your message model objects should conform to the `JSQMessageData` protocol.
* However, you may use the provided `JSQMessage` class.
* **Media Attachment Model**
* Your media attachment model objects should conform to the `JSQMessageMediaData` protocol.
* However, you may use the provided classes: `JSQPhotoMediaItem`, `JSQLocationMediaItem`, `JSQVideoMediaItem`.
* Creating your own custom media items is easy! Simply follow the pattern used by the built-in media types.
* Also see `JSQMessagesMediaViewBubbleImageMasker` for masking your custom media views as message bubbles.
* **Avatar Model**
* Your avatar model objects should conform to the `JSQMessageAvatarImageDataSource` protocol.
* However, you may use the provided `JSQMessagesAvatarImage` class.
* Also see `JSQMessagesAvatarImageFactory` for easily generating custom avatars.
* **Message Bubble Model**
* Your message bubble model objects should conform to the `JSQMessageBubbleImageDataSource` protocol.
* However, you may use the provided `JSQMessagesBubbleImage` class.
* Also see `JSQMessagesBubbleImageFactory` and `UIImage+JSQMessages.h` for easily generating custom bubbles.
* **View Controller**
* Subclass `JSQMessagesViewController`.
* Implement the required methods in the `JSQMessagesCollectionViewDataSource` protocol.
* Implement the required methods in the `JSQMessagesCollectionViewDelegateFlowLayout` protocol.
* Set your `senderId` and `senderDisplayName`. These properties correspond to the methods found in `JSQMessageData` and determine which messages are incoming or outgoing.
* **Customizing**
* The demo project is well-commented. Please use this as a guide.
## Previous versions
Sorry! Guides are not available for older versions of the library.

View File

@ -1,17 +0,0 @@
# Migration Guide
*Migrating between major versions of JSQMessagesViewController?*
-----------------------------
## From `6.x` to `7.x`
See the [7.0 release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/7.0.0) for details about API changes.
## From `5.x` to `6.x`
See the [6.0 release notes](https://github.com/jessesquires/JSQMessagesViewController/releases/tag/6.0.0) for details about API changes.
## Previous versions
Unfortunately, versions prior to `5.0` outdate this document, and guides are not available.

View File

@ -7,10 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
54271E3B1C90469100294290 /* jsq_messages_sample.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 54271E3A1C90469100294290 /* jsq_messages_sample.m4a */; };
54271E3E1C905B9200294290 /* JSQAudioMediaItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 54271E3D1C905B9200294290 /* JSQAudioMediaItem.m */; };
54271E401C905D1600294290 /* JSQAudioMediaItemTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 54271E3F1C905D1600294290 /* JSQAudioMediaItemTests.m */; };
544A32211CB2EE380084BFC0 /* JSQAudioMediaViewAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 544A32201CB2EE380084BFC0 /* JSQAudioMediaViewAttributes.m */; };
36CF33BD29CF36EB06D0CCFD /* libPods-JSQMessagesTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 782026E9E518622532ED474D /* libPods-JSQMessagesTests.a */; };
77CC17A895E6E12BC9CB549A /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 97E6750B77E8A7042BA0754B /* libPods.a */; };
88078A9D19D8FEB5005B4595 /* JSQMessagesMediaPlaceholderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 88078A9C19D8FEB5005B4595 /* JSQMessagesMediaPlaceholderView.m */; };
88324C3419F6301C00BC732D /* JSQMessagesMediaViewBubbleImageMaskerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 88324C3319F6301C00BC732D /* JSQMessagesMediaViewBubbleImageMaskerTests.m */; };
883C11781A09FB100092A16D /* JSQMessagesCellTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 883C11771A09FB100092A16D /* JSQMessagesCellTextView.m */; };
@ -32,8 +30,6 @@
886C33FD19F4371E006B4997 /* JSQVideoMediaItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 886C33FC19F4371E006B4997 /* JSQVideoMediaItem.m */; };
886C33FF19F45E30006B4997 /* JSQMessagesViewController.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 886C33FE19F45E30006B4997 /* JSQMessagesViewController.podspec */; };
886FFD2E19E9A65D00EB8485 /* UIDevice+JSQMessages.m in Sources */ = {isa = PBXBuildFile; fileRef = 886FFD2D19E9A65D00EB8485 /* UIDevice+JSQMessages.m */; };
8873B60C1AB7B244006DF9AC /* NSBundle+JSQMessages.m in Sources */ = {isa = PBXBuildFile; fileRef = 8873B60B1AB7B244006DF9AC /* NSBundle+JSQMessages.m */; };
8873B60E1AB7B63E006DF9AC /* JSQMessagesNSBundleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8873B60D1AB7B63E006DF9AC /* JSQMessagesNSBundleTests.m */; };
8885734A19DE540400E89D20 /* DemoSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8885734919DE540400E89D20 /* DemoSettingsViewController.m */; };
8885734D19DE55D000E89D20 /* NSUserDefaults+DemoSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 8885734C19DE55D000E89D20 /* NSUserDefaults+DemoSettings.m */; };
88A25F3719D8DF2500924534 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F2D19D8DF2500924534 /* AppDelegate.m */; };
@ -62,9 +58,7 @@
88A25FCA19D8E01A00924534 /* JSQMessagesCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F8B19D8E01A00924534 /* JSQMessagesCollectionView.m */; };
88A25FCB19D8E01A00924534 /* JSQMessagesCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F8D19D8E01A00924534 /* JSQMessagesCollectionViewCell.m */; };
88A25FCC19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F8F19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.m */; };
88A25FCD19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.xib in Resources */ = {isa = PBXBuildFile; fileRef = 88A25F9019D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.xib */; };
88A25FCE19D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F9219D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.m */; };
88A25FCF19D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.xib in Resources */ = {isa = PBXBuildFile; fileRef = 88A25F9319D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.xib */; };
88A25FD019D8E01A00924534 /* JSQMessagesComposerTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F9519D8E01A00924534 /* JSQMessagesComposerTextView.m */; };
88A25FD119D8E01A00924534 /* JSQMessagesInputToolbar.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F9719D8E01A00924534 /* JSQMessagesInputToolbar.m */; };
88A25FD219D8E01A00924534 /* JSQMessagesLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F9919D8E01A00924534 /* JSQMessagesLabel.m */; };
@ -103,14 +97,29 @@
88A2601919D8E18400924534 /* JSQMessagesTypingIndicatorFooterViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A2600019D8E18400924534 /* JSQMessagesTypingIndicatorFooterViewTests.m */; };
88A2601B19D8E45600924534 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 88A2601A19D8E45600924534 /* Info.plist */; };
88A901B619F618B100F99777 /* JSQMediaItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A901B519F618B100F99777 /* JSQMediaItem.m */; };
88B5C41F1B7C422900EC79D4 /* JSQMessagesBubblesSizeCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = 88B5C41E1B7C422900EC79D4 /* JSQMessagesBubblesSizeCalculator.m */; };
88C00A4E1A44D4C600B004B3 /* JSQLocationMediaItemTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C00A4D1A44D4C600B004B3 /* JSQLocationMediaItemTests.m */; };
88C00A501A44D4D800B004B3 /* JSQPhotoMediaItemTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C00A4F1A44D4D800B004B3 /* JSQPhotoMediaItemTests.m */; };
88C00A521A44D4E500B004B3 /* JSQVideoMediaItemTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C00A511A44D4E500B004B3 /* JSQVideoMediaItemTests.m */; };
88C4583019F5F7A0008FD427 /* JSQMessagesMediaViewBubbleImageMasker.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C4582F19F5F7A0008FD427 /* JSQMessagesMediaViewBubbleImageMasker.m */; };
BF6DA766BD3B8893A67FB2BD /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C3F882AA48978C11F64DC2DF /* libPods.a */; };
C8994EF7DDBE74B9E3F1A16C /* libPods-JSQMessagesTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E23238C8D8DF79244DEE1787 /* libPods-JSQMessagesTests.a */; };
E8877F1947CE8050ECCD9539 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C3F882AA48978C11F64DC2DF /* libPods.a */; };
88E4D7131A0DBD6B000CC061 /* JSQMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8841B88719F4988800EA16B6 /* JSQMessages.strings */; };
94A4FA20C2FBD0D62614D5A8 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 97E6750B77E8A7042BA0754B /* libPods.a */; };
FC15B7A91A1E880900F59801 /* JSQCallCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = FC15B7A81A1E880900F59801 /* JSQCallCollectionViewCell.xib */; };
FC15B7B01A1F6AC800F59801 /* JSQMessagesCollectionViewCellIncoming.xib in Resources */ = {isa = PBXBuildFile; fileRef = FC15B7AE1A1F6AC800F59801 /* JSQMessagesCollectionViewCellIncoming.xib */; };
FC15B7B11A1F6AC800F59801 /* JSQMessagesCollectionViewCellOutgoing.xib in Resources */ = {isa = PBXBuildFile; fileRef = FC15B7AF1A1F6AC800F59801 /* JSQMessagesCollectionViewCellOutgoing.xib */; };
FC4FA03A1A1E1BD100DA100A /* JSQCall.m in Sources */ = {isa = PBXBuildFile; fileRef = FC4FA0391A1E1BD100DA100A /* JSQCall.m */; };
FC4FA03D1A1E81AF00DA100A /* JSQCallCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FC4FA03C1A1E81AF00DA100A /* JSQCallCollectionViewCell.m */; };
FCA52AEF1A2B6ECE00CCADFA /* call_missed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AEE1A2B6ECE00CCADFA /* call_missed@2x.png */; };
FCA52AF51A2B6FAE00CCADFA /* call_canceled@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AF11A2B6FAE00CCADFA /* call_canceled@2x.png */; };
FCA52AF61A2B6FAE00CCADFA /* call_failed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AF21A2B6FAE00CCADFA /* call_failed@2x.png */; };
FCA52AF71A2B6FAE00CCADFA /* call_incoming@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AF31A2B6FAE00CCADFA /* call_incoming@2x.png */; };
FCA52AF81A2B6FAE00CCADFA /* call_outgoing@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AF41A2B6FAE00CCADFA /* call_outgoing@2x.png */; };
FCA52B021A2B9F0E00CCADFA /* warning_white@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52B001A2B9F0E00CCADFA /* warning_white@2x.png */; };
FCA52B031A2B9F0E00CCADFA /* error_white@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52B011A2B9F0E00CCADFA /* error_white@2x.png */; };
FCFA5E131A29FC1000C8E32E /* JSQDisplayedMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFA5E121A29FC1000C8E32E /* JSQDisplayedMessage.m */; };
FCFA5E161A29FE3B00C8E32E /* JSQInfoMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFA5E151A29FE3B00C8E32E /* JSQInfoMessage.m */; };
FCFA5E191A2A044500C8E32E /* JSQErrorMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFA5E181A2A044500C8E32E /* JSQErrorMessage.m */; };
FCFA5E1D1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFA5E1B1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.m */; };
FCFA5E1E1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = FCFA5E1C1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.xib */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -124,20 +133,30 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
0B4D05069814EB50FB0F4229 /* Pods-JSQMessagesTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JSQMessagesTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-JSQMessagesTests/Pods-JSQMessagesTests.release.xcconfig"; sourceTree = "<group>"; };
1D4D3B82D90888BCEAF890D3 /* Pods-JSQMessagesTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JSQMessagesTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-JSQMessagesTests/Pods-JSQMessagesTests.debug.xcconfig"; sourceTree = "<group>"; };
3BA6237809BE0D008CFE3697 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
54271E3A1C90469100294290 /* jsq_messages_sample.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = jsq_messages_sample.m4a; sourceTree = "<group>"; };
54271E3C1C905B9200294290 /* JSQAudioMediaItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQAudioMediaItem.h; sourceTree = "<group>"; };
54271E3D1C905B9200294290 /* JSQAudioMediaItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQAudioMediaItem.m; sourceTree = "<group>"; };
54271E3F1C905D1600294290 /* JSQAudioMediaItemTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQAudioMediaItemTests.m; sourceTree = "<group>"; };
544A321F1CB2EE380084BFC0 /* JSQAudioMediaViewAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQAudioMediaViewAttributes.h; sourceTree = "<group>"; };
544A32201CB2EE380084BFC0 /* JSQAudioMediaViewAttributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQAudioMediaViewAttributes.m; sourceTree = "<group>"; };
0844AD596023C7658D39E241 /* Pods-JSQMessagesTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JSQMessagesTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-JSQMessagesTests/Pods-JSQMessagesTests.release.xcconfig"; sourceTree = "<group>"; };
223FBACE0F24ADEF8B7F3F24 /* Pods-JSQMessagesTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JSQMessagesTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-JSQMessagesTests/Pods-JSQMessagesTests.debug.xcconfig"; sourceTree = "<group>"; };
27B7FD1B722B36B26CB3460B /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
782026E9E518622532ED474D /* libPods-JSQMessagesTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-JSQMessagesTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
88078A9B19D8FEB5005B4595 /* JSQMessagesMediaPlaceholderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesMediaPlaceholderView.h; sourceTree = "<group>"; };
88078A9C19D8FEB5005B4595 /* JSQMessagesMediaPlaceholderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesMediaPlaceholderView.m; sourceTree = "<group>"; };
88324C3319F6301C00BC732D /* JSQMessagesMediaViewBubbleImageMaskerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesMediaViewBubbleImageMaskerTests.m; sourceTree = "<group>"; };
883C11761A09FB100092A16D /* JSQMessagesCellTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesCellTextView.h; sourceTree = "<group>"; };
883C11771A09FB100092A16D /* JSQMessagesCellTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesCellTextView.m; sourceTree = "<group>"; };
8841B88619F4988800EA16B6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/JSQMessages.strings; sourceTree = "<group>"; };
8841B88819F4988900EA16B6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/JSQMessages.strings; sourceTree = "<group>"; };
8841B88919F4988A00EA16B6 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/JSQMessages.strings; sourceTree = "<group>"; };
8841B88A19F4988B00EA16B6 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/JSQMessages.strings; sourceTree = "<group>"; };
8841B88B19F4988C00EA16B6 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/JSQMessages.strings"; sourceTree = "<group>"; };
8841B88C19F4988F00EA16B6 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/JSQMessages.strings"; sourceTree = "<group>"; };
8841B88D19F4989000EA16B6 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/JSQMessages.strings; sourceTree = "<group>"; };
8841B88E19F4989100EA16B6 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/JSQMessages.strings; sourceTree = "<group>"; };
8841B88F19F4989200EA16B6 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/JSQMessages.strings; sourceTree = "<group>"; };
8841B89019F4989200EA16B6 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/JSQMessages.strings; sourceTree = "<group>"; };
8841B89119F4989300EA16B6 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/JSQMessages.strings; sourceTree = "<group>"; };
8841B89219F4989400EA16B6 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/JSQMessages.strings; sourceTree = "<group>"; };
8841B89319F4989500EA16B6 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/JSQMessages.strings; sourceTree = "<group>"; };
8841B89419F4989500EA16B6 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/JSQMessages.strings; sourceTree = "<group>"; };
8841B89519F4989600EA16B6 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/JSQMessages.strings; sourceTree = "<group>"; };
88445B3019E0AE3F0014F889 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
88445B3219E0AE450014F889 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
88445B3419E0AE4A0014F889 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
@ -153,9 +172,6 @@
886C33FE19F45E30006B4997 /* JSQMessagesViewController.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = JSQMessagesViewController.podspec; sourceTree = "<group>"; };
886FFD2C19E9A65D00EB8485 /* UIDevice+JSQMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIDevice+JSQMessages.h"; sourceTree = "<group>"; };
886FFD2D19E9A65D00EB8485 /* UIDevice+JSQMessages.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIDevice+JSQMessages.m"; sourceTree = "<group>"; };
8873B60A1AB7B244006DF9AC /* NSBundle+JSQMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSBundle+JSQMessages.h"; sourceTree = "<group>"; };
8873B60B1AB7B244006DF9AC /* NSBundle+JSQMessages.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+JSQMessages.m"; sourceTree = "<group>"; };
8873B60D1AB7B63E006DF9AC /* JSQMessagesNSBundleTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesNSBundleTests.m; sourceTree = "<group>"; };
8885734819DE540400E89D20 /* DemoSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoSettingsViewController.h; sourceTree = "<group>"; };
8885734919DE540400E89D20 /* DemoSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoSettingsViewController.m; sourceTree = "<group>"; };
8885734B19DE55D000E89D20 /* NSUserDefaults+DemoSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSUserDefaults+DemoSettings.h"; sourceTree = "<group>"; };
@ -218,10 +234,8 @@
88A25F8D19D8E01A00924534 /* JSQMessagesCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesCollectionViewCell.m; sourceTree = "<group>"; };
88A25F8E19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesCollectionViewCellIncoming.h; sourceTree = "<group>"; };
88A25F8F19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesCollectionViewCellIncoming.m; sourceTree = "<group>"; };
88A25F9019D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JSQMessagesCollectionViewCellIncoming.xib; sourceTree = "<group>"; };
88A25F9119D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesCollectionViewCellOutgoing.h; sourceTree = "<group>"; };
88A25F9219D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesCollectionViewCellOutgoing.m; sourceTree = "<group>"; };
88A25F9319D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JSQMessagesCollectionViewCellOutgoing.xib; sourceTree = "<group>"; };
88A25F9419D8E01A00924534 /* JSQMessagesComposerTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesComposerTextView.h; sourceTree = "<group>"; };
88A25F9519D8E01A00924534 /* JSQMessagesComposerTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesComposerTextView.m; sourceTree = "<group>"; };
88A25F9619D8E01A00924534 /* JSQMessagesInputToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesInputToolbar.h; sourceTree = "<group>"; };
@ -270,17 +284,36 @@
88A2601A19D8E45600924534 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
88A901B419F618B100F99777 /* JSQMediaItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMediaItem.h; sourceTree = "<group>"; };
88A901B519F618B100F99777 /* JSQMediaItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMediaItem.m; sourceTree = "<group>"; };
88B5C41D1B7C422900EC79D4 /* JSQMessagesBubblesSizeCalculator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesBubblesSizeCalculator.h; sourceTree = "<group>"; };
88B5C41E1B7C422900EC79D4 /* JSQMessagesBubblesSizeCalculator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesBubblesSizeCalculator.m; sourceTree = "<group>"; };
88B5C4201B7C424700EC79D4 /* JSQMessagesBubbleSizeCalculating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesBubbleSizeCalculating.h; sourceTree = "<group>"; };
88C00A4D1A44D4C600B004B3 /* JSQLocationMediaItemTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQLocationMediaItemTests.m; sourceTree = "<group>"; };
88C00A4F1A44D4D800B004B3 /* JSQPhotoMediaItemTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQPhotoMediaItemTests.m; sourceTree = "<group>"; };
88C00A511A44D4E500B004B3 /* JSQVideoMediaItemTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQVideoMediaItemTests.m; sourceTree = "<group>"; };
88C4582E19F5F7A0008FD427 /* JSQMessagesMediaViewBubbleImageMasker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesMediaViewBubbleImageMasker.h; sourceTree = "<group>"; };
88C4582F19F5F7A0008FD427 /* JSQMessagesMediaViewBubbleImageMasker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesMediaViewBubbleImageMasker.m; sourceTree = "<group>"; };
AD6E75315517DE46FE495B65 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
C3F882AA48978C11F64DC2DF /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
E23238C8D8DF79244DEE1787 /* libPods-JSQMessagesTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-JSQMessagesTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
97E6750B77E8A7042BA0754B /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
FC15B7A81A1E880900F59801 /* JSQCallCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JSQCallCollectionViewCell.xib; sourceTree = "<group>"; };
FC15B7AE1A1F6AC800F59801 /* JSQMessagesCollectionViewCellIncoming.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JSQMessagesCollectionViewCellIncoming.xib; sourceTree = "<group>"; };
FC15B7AF1A1F6AC800F59801 /* JSQMessagesCollectionViewCellOutgoing.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JSQMessagesCollectionViewCellOutgoing.xib; sourceTree = "<group>"; };
FC4FA0381A1E1BD100DA100A /* JSQCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQCall.h; sourceTree = "<group>"; };
FC4FA0391A1E1BD100DA100A /* JSQCall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQCall.m; sourceTree = "<group>"; };
FC4FA03B1A1E81AF00DA100A /* JSQCallCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQCallCollectionViewCell.h; sourceTree = "<group>"; };
FC4FA03C1A1E81AF00DA100A /* JSQCallCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQCallCollectionViewCell.m; sourceTree = "<group>"; };
FC5C727E4CCDA2B95A7BA30C /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
FCA52AEE1A2B6ECE00CCADFA /* call_missed@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "call_missed@2x.png"; path = "../../JSQMessagesDemo/call_missed@2x.png"; sourceTree = "<group>"; };
FCA52AF11A2B6FAE00CCADFA /* call_canceled@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_canceled@2x.png"; sourceTree = "<group>"; };
FCA52AF21A2B6FAE00CCADFA /* call_failed@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_failed@2x.png"; sourceTree = "<group>"; };
FCA52AF31A2B6FAE00CCADFA /* call_incoming@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_incoming@2x.png"; sourceTree = "<group>"; };
FCA52AF41A2B6FAE00CCADFA /* call_outgoing@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_outgoing@2x.png"; sourceTree = "<group>"; };
FCA52B001A2B9F0E00CCADFA /* warning_white@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "warning_white@2x.png"; sourceTree = "<group>"; };
FCA52B011A2B9F0E00CCADFA /* error_white@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "error_white@2x.png"; sourceTree = "<group>"; };
FCFA5E111A29FC1000C8E32E /* JSQDisplayedMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQDisplayedMessage.h; sourceTree = "<group>"; };
FCFA5E121A29FC1000C8E32E /* JSQDisplayedMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQDisplayedMessage.m; sourceTree = "<group>"; };
FCFA5E141A29FE3B00C8E32E /* JSQInfoMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQInfoMessage.h; sourceTree = "<group>"; };
FCFA5E151A29FE3B00C8E32E /* JSQInfoMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQInfoMessage.m; sourceTree = "<group>"; };
FCFA5E171A2A044500C8E32E /* JSQErrorMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQErrorMessage.h; sourceTree = "<group>"; };
FCFA5E181A2A044500C8E32E /* JSQErrorMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQErrorMessage.m; sourceTree = "<group>"; };
FCFA5E1A1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQDisplayedMessageCollectionViewCell.h; sourceTree = "<group>"; };
FCFA5E1B1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQDisplayedMessageCollectionViewCell.m; sourceTree = "<group>"; };
FCFA5E1C1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JSQDisplayedMessageCollectionViewCell.xib; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -294,7 +327,7 @@
88445B3519E0AE4A0014F889 /* CoreGraphics.framework in Frameworks */,
88445B3319E0AE450014F889 /* Foundation.framework in Frameworks */,
88445B3119E0AE3F0014F889 /* UIKit.framework in Frameworks */,
E8877F1947CE8050ECCD9539 /* libPods.a in Frameworks */,
77CC17A895E6E12BC9CB549A /* libPods.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -309,39 +342,48 @@
88445B3B19E0C0B10014F889 /* XCTest.framework in Frameworks */,
88445B3919E0C0AC0014F889 /* Foundation.framework in Frameworks */,
88445B3819E0C0A70014F889 /* UIKit.framework in Frameworks */,
C8994EF7DDBE74B9E3F1A16C /* libPods-JSQMessagesTests.a in Frameworks */,
BF6DA766BD3B8893A67FB2BD /* libPods.a in Frameworks */,
94A4FA20C2FBD0D62614D5A8 /* libPods.a in Frameworks */,
36CF33BD29CF36EB06D0CCFD /* libPods-JSQMessagesTests.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
2BBEF3CD91C31A49E5FF9E3C /* Pods */ = {
isa = PBXGroup;
children = (
FC5C727E4CCDA2B95A7BA30C /* Pods.debug.xcconfig */,
27B7FD1B722B36B26CB3460B /* Pods.release.xcconfig */,
223FBACE0F24ADEF8B7F3F24 /* Pods-JSQMessagesTests.debug.xcconfig */,
0844AD596023C7658D39E241 /* Pods-JSQMessagesTests.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
636A8663AEEE5C37B65C515D /* Frameworks */ = {
isa = PBXGroup;
children = (
88445B3419E0AE4A0014F889 /* CoreGraphics.framework */,
88445B4119E1B50B0014F889 /* CoreLocation.framework */,
88445B3219E0AE450014F889 /* Foundation.framework */,
88445B4319E1B5110014F889 /* MapKit.framework */,
88445B4119E1B50B0014F889 /* CoreLocation.framework */,
88445B3419E0AE4A0014F889 /* CoreGraphics.framework */,
88445B3219E0AE450014F889 /* Foundation.framework */,
782026E9E518622532ED474D /* libPods-JSQMessagesTests.a */,
97E6750B77E8A7042BA0754B /* libPods.a */,
88445B3619E0AE5C0014F889 /* QuartzCore.framework */,
88445B3019E0AE3F0014F889 /* UIKit.framework */,
88445B3A19E0C0B10014F889 /* XCTest.framework */,
C3F882AA48978C11F64DC2DF /* libPods.a */,
E23238C8D8DF79244DEE1787 /* libPods-JSQMessagesTests.a */,
);
name = Frameworks;
path = ../..;
sourceTree = "<group>";
};
842892590A65F355D8619D29 /* Pods */ = {
8841B88219F4983C00EA16B6 /* Strings */ = {
isa = PBXGroup;
children = (
3BA6237809BE0D008CFE3697 /* Pods.debug.xcconfig */,
AD6E75315517DE46FE495B65 /* Pods.release.xcconfig */,
1D4D3B82D90888BCEAF890D3 /* Pods-JSQMessagesTests.debug.xcconfig */,
0B4D05069814EB50FB0F4229 /* Pods-JSQMessagesTests.release.xcconfig */,
8841B88719F4988800EA16B6 /* JSQMessages.strings */,
);
name = Pods;
path = Strings;
sourceTree = "<group>";
};
88A25EF919D8DEC400924534 = {
@ -349,11 +391,10 @@
children = (
886C33FE19F45E30006B4997 /* JSQMessagesViewController.podspec */,
88A25F3E19D8E01A00924534 /* JSQMessagesViewController */,
636A8663AEEE5C37B65C515D /* Frameworks */,
88A25F2B19D8DF2500924534 /* JSQMessagesDemo */,
88A25F1E19D8DEC500924534 /* JSQMessagesTests */,
2BBEF3CD91C31A49E5FF9E3C /* Pods */,
88A25F0319D8DEC400924534 /* Products */,
842892590A65F355D8619D29 /* Pods */,
);
sourceTree = "<group>";
};
@ -391,7 +432,6 @@
88A25F2B19D8DF2500924534 /* JSQMessagesDemo */ = {
isa = PBXGroup;
children = (
54271E3A1C90469100294290 /* jsq_messages_sample.m4a */,
88A25F2C19D8DF2500924534 /* AppDelegate.h */,
88A25F2D19D8DF2500924534 /* AppDelegate.m */,
88A25FD919D8E0C400924534 /* DemoMessagesViewController.h */,
@ -430,6 +470,9 @@
88A25F3F19D8E01A00924534 /* Assets */ = {
isa = PBXGroup;
children = (
FCA52AFB1A2B9BAD00CCADFA /* InfoError */,
FCA52AF01A2B6F8A00CCADFA /* Calls */,
8841B88219F4983C00EA16B6 /* Strings */,
8861666C19F492B70025B958 /* JSQMessagesAssets.bundle */,
);
path = Assets;
@ -440,8 +483,6 @@
children = (
88A25F5519D8E01A00924534 /* JSQSystemSoundPlayer+JSQMessages.h */,
88A25F5619D8E01A00924534 /* JSQSystemSoundPlayer+JSQMessages.m */,
8873B60A1AB7B244006DF9AC /* NSBundle+JSQMessages.h */,
8873B60B1AB7B244006DF9AC /* NSBundle+JSQMessages.m */,
88A25F5719D8E01A00924534 /* NSString+JSQMessages.h */,
88A25F5819D8E01A00924534 /* NSString+JSQMessages.m */,
88A25F5919D8E01A00924534 /* UIColor+JSQMessages.h */,
@ -488,11 +529,6 @@
88A25F6F19D8E01A00924534 /* Layout */ = {
isa = PBXGroup;
children = (
544A321F1CB2EE380084BFC0 /* JSQAudioMediaViewAttributes.h */,
544A32201CB2EE380084BFC0 /* JSQAudioMediaViewAttributes.m */,
88B5C4201B7C424700EC79D4 /* JSQMessagesBubbleSizeCalculating.h */,
88B5C41D1B7C422900EC79D4 /* JSQMessagesBubblesSizeCalculator.h */,
88B5C41E1B7C422900EC79D4 /* JSQMessagesBubblesSizeCalculator.m */,
88A25F7019D8E01A00924534 /* JSQMessagesCollectionViewFlowLayout.h */,
88A25F7119D8E01A00924534 /* JSQMessagesCollectionViewFlowLayout.m */,
88A25F7219D8E01A00924534 /* JSQMessagesCollectionViewFlowLayoutInvalidationContext.h */,
@ -506,8 +542,6 @@
88A25F7619D8E01A00924534 /* Model */ = {
isa = PBXGroup;
children = (
54271E3C1C905B9200294290 /* JSQAudioMediaItem.h */,
54271E3D1C905B9200294290 /* JSQAudioMediaItem.m */,
88445B3E19E1B4470014F889 /* JSQLocationMediaItem.h */,
88445B3F19E1B4470014F889 /* JSQLocationMediaItem.m */,
88A901B419F618B100F99777 /* JSQMediaItem.h */,
@ -528,6 +562,14 @@
88A25F8619D8E01A00924534 /* JSQPhotoMediaItem.m */,
886C33FB19F4371E006B4997 /* JSQVideoMediaItem.h */,
886C33FC19F4371E006B4997 /* JSQVideoMediaItem.m */,
FC4FA0381A1E1BD100DA100A /* JSQCall.h */,
FC4FA0391A1E1BD100DA100A /* JSQCall.m */,
FCFA5E111A29FC1000C8E32E /* JSQDisplayedMessage.h */,
FCFA5E121A29FC1000C8E32E /* JSQDisplayedMessage.m */,
FCFA5E141A29FE3B00C8E32E /* JSQInfoMessage.h */,
FCFA5E151A29FE3B00C8E32E /* JSQInfoMessage.m */,
FCFA5E171A2A044500C8E32E /* JSQErrorMessage.h */,
FCFA5E181A2A044500C8E32E /* JSQErrorMessage.m */,
);
path = Model;
sourceTree = "<group>";
@ -535,6 +577,7 @@
88A25F8919D8E01A00924534 /* Views */ = {
isa = PBXGroup;
children = (
636A8663AEEE5C37B65C515D /* Frameworks */,
883C11761A09FB100092A16D /* JSQMessagesCellTextView.h */,
883C11771A09FB100092A16D /* JSQMessagesCellTextView.m */,
88A25F8A19D8E01A00924534 /* JSQMessagesCollectionView.h */,
@ -543,10 +586,10 @@
88A25F8D19D8E01A00924534 /* JSQMessagesCollectionViewCell.m */,
88A25F8E19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.h */,
88A25F8F19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.m */,
88A25F9019D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.xib */,
FC15B7AE1A1F6AC800F59801 /* JSQMessagesCollectionViewCellIncoming.xib */,
88A25F9119D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.h */,
88A25F9219D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.m */,
88A25F9319D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.xib */,
FC15B7AF1A1F6AC800F59801 /* JSQMessagesCollectionViewCellOutgoing.xib */,
88A25F9419D8E01A00924534 /* JSQMessagesComposerTextView.h */,
88A25F9519D8E01A00924534 /* JSQMessagesComposerTextView.m */,
88A25F9619D8E01A00924534 /* JSQMessagesInputToolbar.h */,
@ -564,6 +607,12 @@
88A25FA019D8E01A00924534 /* JSQMessagesTypingIndicatorFooterView.h */,
88A25FA119D8E01A00924534 /* JSQMessagesTypingIndicatorFooterView.m */,
88A25FA219D8E01A00924534 /* JSQMessagesTypingIndicatorFooterView.xib */,
FC4FA03B1A1E81AF00DA100A /* JSQCallCollectionViewCell.h */,
FC4FA03C1A1E81AF00DA100A /* JSQCallCollectionViewCell.m */,
FC15B7A81A1E880900F59801 /* JSQCallCollectionViewCell.xib */,
FCFA5E1A1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.h */,
FCFA5E1B1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.m */,
FCFA5E1C1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.xib */,
);
path = Views;
sourceTree = "<group>";
@ -571,7 +620,6 @@
88A25FE219D8E18400924534 /* CategoryTests */ = {
isa = PBXGroup;
children = (
8873B60D1AB7B63E006DF9AC /* JSQMessagesNSBundleTests.m */,
88A25FE319D8E18400924534 /* JSQMessagesNSStringTests.m */,
88A25FE419D8E18400924534 /* JSQMessagesUIColorTests.m */,
88A25FE519D8E18400924534 /* JSQMessagesUIImageTests.m */,
@ -613,7 +661,6 @@
88A25FF219D8E18400924534 /* ModelTests */ = {
isa = PBXGroup;
children = (
54271E3F1C905D1600294290 /* JSQAudioMediaItemTests.m */,
88C00A4D1A44D4C600B004B3 /* JSQLocationMediaItemTests.m */,
88A25FF319D8E18400924534 /* JSQMessageMediaTests.m */,
88A25FF419D8E18400924534 /* JSQMessagesAvatarImageTests.m */,
@ -640,6 +687,27 @@
path = ViewTests;
sourceTree = "<group>";
};
FCA52AF01A2B6F8A00CCADFA /* Calls */ = {
isa = PBXGroup;
children = (
FCA52AF11A2B6FAE00CCADFA /* call_canceled@2x.png */,
FCA52AF21A2B6FAE00CCADFA /* call_failed@2x.png */,
FCA52AF31A2B6FAE00CCADFA /* call_incoming@2x.png */,
FCA52AF41A2B6FAE00CCADFA /* call_outgoing@2x.png */,
FCA52AEE1A2B6ECE00CCADFA /* call_missed@2x.png */,
);
name = Calls;
sourceTree = "<group>";
};
FCA52AFB1A2B9BAD00CCADFA /* InfoError */ = {
isa = PBXGroup;
children = (
FCA52B001A2B9F0E00CCADFA /* warning_white@2x.png */,
FCA52B011A2B9F0E00CCADFA /* error_white@2x.png */,
);
name = InfoError;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -647,12 +715,11 @@
isa = PBXNativeTarget;
buildConfigurationList = 88A25F2519D8DEC500924534 /* Build configuration list for PBXNativeTarget "JSQMessages" */;
buildPhases = (
90945CFDCD14BCFE538D66C9 /* Check Pods Manifest.lock */,
3AF3068570D5C74873D84E30 /* Check Pods Manifest.lock */,
88A25EFE19D8DEC400924534 /* Sources */,
88A25EFF19D8DEC400924534 /* Frameworks */,
88A25F0019D8DEC400924534 /* Resources */,
C8D68BB894C4DD38C5615198 /* Embed Pods Frameworks */,
908FA537E0B2FD4A94A60411 /* Copy Pods Resources */,
4CCCD7A86E86CB86C48E303C /* Copy Pods Resources */,
);
buildRules = (
);
@ -667,12 +734,11 @@
isa = PBXNativeTarget;
buildConfigurationList = 88A25F2819D8DEC500924534 /* Build configuration list for PBXNativeTarget "JSQMessagesTests" */;
buildPhases = (
95BD949B70ECF8FE9CDDB707 /* Check Pods Manifest.lock */,
F4044DAC71D69462CA8CAE98 /* Check Pods Manifest.lock */,
88A25F1719D8DEC400924534 /* Sources */,
88A25F1819D8DEC400924534 /* Frameworks */,
88A25F1919D8DEC400924534 /* Resources */,
78F522A7ECBD8D8774672696 /* Embed Pods Frameworks */,
B85CD3AA4EFCF4765BE7FAD9 /* Copy Pods Resources */,
F6B484334A138916FC111868 /* Copy Pods Resources */,
);
buildRules = (
);
@ -690,7 +756,7 @@
88A25EFA19D8DEC400924534 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0700;
LastUpgradeCheck = 0600;
ORGANIZATIONNAME = "Hexed Bits";
TargetAttributes = {
88A25F0119D8DEC400924534 = {
@ -739,17 +805,26 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
88E4D7131A0DBD6B000CC061 /* JSQMessages.strings in Resources */,
886C33FF19F45E30006B4997 /* JSQMessagesViewController.podspec in Resources */,
8861666D19F492B70025B958 /* JSQMessagesAssets.bundle in Resources */,
88A25FCF19D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.xib in Resources */,
88A25FCD19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.xib in Resources */,
FC15B7B11A1F6AC800F59801 /* JSQMessagesCollectionViewCellOutgoing.xib in Resources */,
88A25FD619D8E01A00924534 /* JSQMessagesToolbarContentView.xib in Resources */,
FCA52AF71A2B6FAE00CCADFA /* call_incoming@2x.png in Resources */,
88A25F3A19D8DF2500924534 /* Images.xcassets in Resources */,
54271E3B1C90469100294290 /* jsq_messages_sample.m4a in Resources */,
88A25FBC19D8E01A00924534 /* JSQMessagesViewController.xib in Resources */,
FCA52AF81A2B6FAE00CCADFA /* call_outgoing@2x.png in Resources */,
FCA52B021A2B9F0E00CCADFA /* warning_white@2x.png in Resources */,
FCA52AF51A2B6FAE00CCADFA /* call_canceled@2x.png in Resources */,
FCA52B031A2B9F0E00CCADFA /* error_white@2x.png in Resources */,
FCA52AEF1A2B6ECE00CCADFA /* call_missed@2x.png in Resources */,
88A25FD819D8E01A00924534 /* JSQMessagesTypingIndicatorFooterView.xib in Resources */,
FCFA5E1E1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.xib in Resources */,
88A25F3919D8DF2500924534 /* Main.storyboard in Resources */,
FC15B7B01A1F6AC800F59801 /* JSQMessagesCollectionViewCellIncoming.xib in Resources */,
88A25FD419D8E01A00924534 /* JSQMessagesLoadEarlierHeaderView.xib in Resources */,
FC15B7A91A1E880900F59801 /* JSQCallCollectionViewCell.xib in Resources */,
FCA52AF61A2B6FAE00CCADFA /* call_failed@2x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -764,22 +839,22 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
78F522A7ECBD8D8774672696 /* Embed Pods Frameworks */ = {
3AF3068570D5C74873D84E30 /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
name = "Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
908FA537E0B2FD4A94A60411 /* Copy Pods Resources */ = {
4CCCD7A86E86CB86C48E303C /* Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -794,7 +869,7 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
showEnvVarsInLog = 0;
};
90945CFDCD14BCFE538D66C9 /* Check Pods Manifest.lock */ = {
F4044DAC71D69462CA8CAE98 /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -809,22 +884,7 @@
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
95BD949B70ECF8FE9CDDB707 /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
B85CD3AA4EFCF4765BE7FAD9 /* Copy Pods Resources */ = {
F6B484334A138916FC111868 /* Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -839,21 +899,6 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-JSQMessagesTests/Pods-JSQMessagesTests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
C8D68BB894C4DD38C5615198 /* Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -867,9 +912,9 @@
88A25FCB19D8E01A00924534 /* JSQMessagesCollectionViewCell.m in Sources */,
88A25FBB19D8E01A00924534 /* JSQMessagesViewController.m in Sources */,
8885734D19DE55D000E89D20 /* NSUserDefaults+DemoSettings.m in Sources */,
544A32211CB2EE380084BFC0 /* JSQAudioMediaViewAttributes.m in Sources */,
883C11781A09FB100092A16D /* JSQMessagesCellTextView.m in Sources */,
88A25FB919D8E01A00924534 /* UIView+JSQMessages.m in Sources */,
FCFA5E131A29FC1000C8E32E /* JSQDisplayedMessage.m in Sources */,
88A25FCA19D8E01A00924534 /* JSQMessagesCollectionView.m in Sources */,
88A25FD219D8E01A00924534 /* JSQMessagesLabel.m in Sources */,
88445B4019E1B4470014F889 /* JSQLocationMediaItem.m in Sources */,
@ -877,21 +922,23 @@
88A25FD519D8E01A00924534 /* JSQMessagesToolbarContentView.m in Sources */,
88A25FC119D8E01A00924534 /* JSQMessagesCollectionViewFlowLayout.m in Sources */,
8885734A19DE540400E89D20 /* DemoSettingsViewController.m in Sources */,
FC4FA03A1A1E1BD100DA100A /* JSQCall.m in Sources */,
88A25FC719D8E01A00924534 /* JSQMessagesBubbleImage.m in Sources */,
88A25FC519D8E01A00924534 /* JSQMessage.m in Sources */,
88A25FD719D8E01A00924534 /* JSQMessagesTypingIndicatorFooterView.m in Sources */,
88A25FD319D8E01A00924534 /* JSQMessagesLoadEarlierHeaderView.m in Sources */,
FC4FA03D1A1E81AF00DA100A /* JSQCallCollectionViewCell.m in Sources */,
88A25FC819D8E01A00924534 /* JSQPhotoMediaItem.m in Sources */,
88C4583019F5F7A0008FD427 /* JSQMessagesMediaViewBubbleImageMasker.m in Sources */,
88A25FB819D8E01A00924534 /* UIImage+JSQMessages.m in Sources */,
88A25FBF19D8E01A00924534 /* JSQMessagesTimestampFormatter.m in Sources */,
88A25FE019D8E0C400924534 /* DemoModelData.m in Sources */,
FCFA5E1D1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.m in Sources */,
88A25F3C19D8DF2500924534 /* main.m in Sources */,
88A25F3719D8DF2500924534 /* AppDelegate.m in Sources */,
54271E3E1C905B9200294290 /* JSQAudioMediaItem.m in Sources */,
886FFD2E19E9A65D00EB8485 /* UIDevice+JSQMessages.m in Sources */,
88B5C41F1B7C422900EC79D4 /* JSQMessagesBubblesSizeCalculator.m in Sources */,
88A25FB619D8E01A00924534 /* NSString+JSQMessages.m in Sources */,
FCFA5E191A2A044500C8E32E /* JSQErrorMessage.m in Sources */,
88A901B619F618B100F99777 /* JSQMediaItem.m in Sources */,
88A25FCC19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.m in Sources */,
88A25FBE19D8E01A00924534 /* JSQMessagesBubbleImageFactory.m in Sources */,
@ -899,12 +946,12 @@
88A25FB719D8E01A00924534 /* UIColor+JSQMessages.m in Sources */,
886C33FD19F4371E006B4997 /* JSQVideoMediaItem.m in Sources */,
88A25FBA19D8E01A00924534 /* JSQMessagesKeyboardController.m in Sources */,
FCFA5E161A29FE3B00C8E32E /* JSQInfoMessage.m in Sources */,
88A25FC019D8E01A00924534 /* JSQMessagesToolbarButtonFactory.m in Sources */,
88A25FC219D8E01A00924534 /* JSQMessagesCollectionViewFlowLayoutInvalidationContext.m in Sources */,
88A25FE119D8E0C400924534 /* TableViewController.m in Sources */,
88A25FBD19D8E01A00924534 /* JSQMessagesAvatarImageFactory.m in Sources */,
88A25FB519D8E01A00924534 /* JSQSystemSoundPlayer+JSQMessages.m in Sources */,
8873B60C1AB7B244006DF9AC /* NSBundle+JSQMessages.m in Sources */,
88A25FD019D8E01A00924534 /* JSQMessagesComposerTextView.m in Sources */,
88A25FC319D8E01A00924534 /* JSQMessagesCollectionViewLayoutAttributes.m in Sources */,
);
@ -919,7 +966,6 @@
88C00A521A44D4E500B004B3 /* JSQVideoMediaItemTests.m in Sources */,
88A2601519D8E18400924534 /* JSQMessagesInputToolbarTests.m in Sources */,
88A2601719D8E18400924534 /* JSQMessagesLoadEarlierHeaderViewTests.m in Sources */,
54271E401C905D1600294290 /* JSQAudioMediaItemTests.m in Sources */,
88A2601219D8E18400924534 /* JSQMessagesCollectionViewCellTests.m in Sources */,
88A2601619D8E18400924534 /* JSQMessagesLabelTests.m in Sources */,
88A2600B19D8E18400924534 /* JSQMessagesCollectionViewFlowLayoutTests.m in Sources */,
@ -939,7 +985,6 @@
88A2601919D8E18400924534 /* JSQMessagesTypingIndicatorFooterViewTests.m in Sources */,
88A2600319D8E18400924534 /* JSQMessagesUIImageTests.m in Sources */,
88C00A4E1A44D4C600B004B3 /* JSQLocationMediaItemTests.m in Sources */,
8873B60E1AB7B63E006DF9AC /* JSQMessagesNSBundleTests.m in Sources */,
88A2600C19D8E18400924534 /* JSQMessagesCollectionViewLayoutAttributesTests.m in Sources */,
88A2600619D8E18400924534 /* JSQMessagesViewControllerTests.m in Sources */,
88A2600519D8E18400924534 /* JSQMessagesKeyboardControllerTests.m in Sources */,
@ -958,6 +1003,28 @@
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
8841B88719F4988800EA16B6 /* JSQMessages.strings */ = {
isa = PBXVariantGroup;
children = (
8841B88619F4988800EA16B6 /* Base */,
8841B88819F4988900EA16B6 /* en */,
8841B88919F4988A00EA16B6 /* es */,
8841B88A19F4988B00EA16B6 /* de */,
8841B88B19F4988C00EA16B6 /* zh-Hans */,
8841B88C19F4988F00EA16B6 /* zh-Hant */,
8841B88D19F4989000EA16B6 /* ro */,
8841B88E19F4989100EA16B6 /* pl */,
8841B88F19F4989200EA16B6 /* ru */,
8841B89019F4989200EA16B6 /* pt */,
8841B89119F4989300EA16B6 /* fr */,
8841B89219F4989400EA16B6 /* it */,
8841B89319F4989500EA16B6 /* he */,
8841B89419F4989500EA16B6 /* nl */,
8841B89519F4989600EA16B6 /* tr */,
);
name = JSQMessages.strings;
sourceTree = "<group>";
};
88A25F3019D8DF2500924534 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
@ -989,7 +1056,6 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@ -1050,7 +1116,7 @@
};
88A25F2619D8DEC500924534 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3BA6237809BE0D008CFE3697 /* Pods.debug.xcconfig */;
baseConfigurationReference = FC5C727E4CCDA2B95A7BA30C /* Pods.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
@ -1061,7 +1127,6 @@
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = "com.hexedbits.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
};
@ -1069,7 +1134,7 @@
};
88A25F2719D8DEC500924534 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = AD6E75315517DE46FE495B65 /* Pods.release.xcconfig */;
baseConfigurationReference = 27B7FD1B722B36B26CB3460B /* Pods.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
@ -1080,7 +1145,6 @@
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = "com.hexedbits.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
};
@ -1088,18 +1152,20 @@
};
88A25F2919D8DEC500924534 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1D4D3B82D90888BCEAF890D3 /* Pods-JSQMessagesTests.debug.xcconfig */;
baseConfigurationReference = 223FBACE0F24ADEF8B7F3F24 /* Pods-JSQMessagesTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = JSQMessagesTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.hexedbits.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JSQMessages.app/JSQMessages";
};
@ -1107,14 +1173,16 @@
};
88A25F2A19D8DEC500924534 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0B4D05069814EB50FB0F4229 /* Pods-JSQMessagesTests.release.xcconfig */;
baseConfigurationReference = 0844AD596023C7658D39E241 /* Pods-JSQMessagesTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = JSQMessagesTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.hexedbits.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JSQMessages.app/JSQMessages";
};

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0730"
LastUpgradeVersion = "0600"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -14,7 +14,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D14DE867BBE115B80620BD22C0E35F79"
BlueprintIdentifier = "4F6B28C25B7B1259BD8C5B8B"
BuildableName = "libPods.a"
BlueprintName = "Pods"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
@ -51,10 +51,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
<TestableReference
skipped = "NO">
@ -76,21 +76,17 @@
ReferencedContainer = "container:JSQMessages.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "88A25F0119D8DEC400924534"
@ -103,13 +99,12 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "88A25F0119D8DEC400924534"

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="JRd-Be-psV">
<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">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
<deployment defaultVersion="1792" identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6238"/>
</dependencies>
<scenes>
<!--Root View Controller-->
@ -12,11 +12,10 @@
<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"/>
<animations/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="CellIdentifier" textLabel="2qz-Z2-GmT" style="IBUITableViewCellStyleDefault" id="k8B-cw-dMU">
<rect key="frame" x="0.0" y="114" width="320" height="44"/>
<rect key="frame" x="0.0" y="119" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="k8B-cw-dMU" id="kX4-QF-oKx">
<rect key="frame" x="0.0" y="0.0" width="287" height="43"/>
@ -25,15 +24,12 @@
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="2qz-Z2-GmT">
<rect key="frame" x="15" y="0.0" width="270" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="18"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
</tableViewCellContentView>
<animations/>
</tableViewCell>
</prototypes>
</tableView>
@ -55,21 +51,17 @@
<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"/>
<animations/>
<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">
<rect key="frame" x="0.0" y="114" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Eii-ro-1yZ" id="qU9-o3-MWC">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<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"/>
<animations/>
<constraints>
<constraint firstAttribute="width" constant="49" id="A6s-Sr-u8U"/>
<constraint firstAttribute="height" constant="31" id="z9i-uJ-MBq"/>
@ -80,34 +72,29 @@
</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"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
<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 firstAttribute="centerY" secondItem="K7N-os-fuc" secondAttribute="centerY" id="j7N-59-vRk"/>
<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>
<animations/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="bZI-G1-eYA">
<rect key="frame" x="0.0" y="158" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="bZI-G1-eYA" id="1Ho-Zz-KN0">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<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"/>
<animations/>
<constraints>
<constraint firstAttribute="height" constant="31" id="gM4-dK-cl7"/>
<constraint firstAttribute="width" constant="49" id="hvu-Yy-NTG"/>
@ -118,34 +105,29 @@
</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"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
<constraints>
<constraint firstAttribute="centerY" secondItem="hMq-Ee-EJK" secondAttribute="centerY" id="CcO-KD-31y"/>
<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>
<animations/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="2Th-gL-oAN">
<rect key="frame" x="0.0" y="202" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="2Th-gL-oAN" id="OFq-Mz-mbl">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<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"/>
<animations/>
<constraints>
<constraint firstAttribute="width" constant="49" id="SaV-RG-DVL"/>
<constraint firstAttribute="height" constant="31" id="dXb-pb-etA"/>
@ -156,38 +138,33 @@
</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"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
<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 firstAttribute="centerY" secondItem="baL-Tb-bTJ" secondAttribute="centerY" id="hx4-cn-W0h"/>
<constraint firstItem="baL-Tb-bTJ" firstAttribute="top" secondItem="OFq-Mz-mbl" secondAttribute="top" constant="6" id="v5e-xk-srk"/>
</constraints>
</tableViewCellContentView>
<animations/>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Avatars" id="ns0-OO-PGu">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="hYS-4f-iL6">
<rect key="frame" x="0.0" y="289" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hYS-4f-iL6" id="dk1-tc-gux">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<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"/>
<animations/>
<constraints>
<constraint firstAttribute="width" constant="49" id="1lf-6y-hgz"/>
<constraint firstAttribute="height" constant="31" id="rdQ-ol-d20"/>
@ -198,34 +175,29 @@
</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"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
<constraints>
<constraint firstAttribute="centerY" secondItem="fLZ-NC-aPO" secondAttribute="centerY" id="17e-cC-bP4"/>
<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>
<animations/>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="VF7-uo-6Pc">
<rect key="frame" x="0.0" y="333" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="VF7-uo-6Pc" id="zad-JQ-TRI">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<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"/>
<animations/>
<constraints>
<constraint firstAttribute="height" constant="31" id="QXv-ty-g0B"/>
<constraint firstAttribute="width" constant="49" id="rZ3-cO-f8t"/>
@ -236,38 +208,33 @@
</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"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
<constraints>
<constraint firstAttribute="centerY" secondItem="LuM-mk-Zj6" secondAttribute="centerY" id="2oC-JM-LVI"/>
<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>
<animations/>
</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">
<rect key="frame" x="0.0" y="420" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="q07-lZ-YdI" id="btE-Mk-fSE">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<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"/>
<animations/>
<constraints>
<constraint firstAttribute="height" constant="31" id="5bI-xQ-njj"/>
<constraint firstAttribute="width" constant="49" id="PG2-X2-FdD"/>
@ -278,23 +245,21 @@
</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"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
<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="centerY" secondItem="uXC-2j-cgi" secondAttribute="centerY" id="zJf-Xj-C1X"/>
<constraint firstAttribute="trailing" secondItem="uXC-2j-cgi" secondAttribute="trailing" constant="8" id="zzu-aP-ZiL"/>
</constraints>
</tableViewCellContentView>
<animations/>
</tableViewCell>
</cells>
</tableViewSection>
@ -324,7 +289,6 @@
<navigationController definesPresentationContext="YES" id="s4z-xn-r6C" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" id="G3q-Gy-0Lf">
<autoresizingMask key="autoresizingMask"/>
<animations/>
</navigationBar>
<connections>
<segue destination="2Qx-iu-03V" kind="relationship" relationship="rootViewController" id="cuu-7c-yOr"/>
@ -345,7 +309,6 @@
<view key="view" contentMode="scaleToFill" id="Vop-TB-ImV">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
<navigationItem key="navigationItem" id="URv-4c-d6h"/>
@ -360,7 +323,6 @@
<navigationController definesPresentationContext="YES" id="JRd-Be-psV" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" id="YZb-OI-WKd">
<autoresizingMask key="autoresizingMask"/>
<animations/>
</navigationBar>
<connections>
<segue destination="rXs-qR-ns2" kind="relationship" relationship="rootViewController" id="8xe-QC-QaY"/>
@ -381,7 +343,6 @@
<view key="view" contentMode="scaleToFill" id="SsE-pA-zOd">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
<navigationItem key="navigationItem" id="gBw-Dh-o4F"/>
@ -391,4 +352,9 @@
<point key="canvasLocation" x="-1989" y="619"/>
</scene>
</scenes>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View File

@ -35,7 +35,7 @@
@interface DemoMessagesViewController : JSQMessagesViewController <UIActionSheetDelegate, JSQMessagesComposerTextViewPasteDelegate>
@interface DemoMessagesViewController : JSQMessagesViewController <UIActionSheetDelegate>
@property (weak, nonatomic) id<JSQDemoViewControllerDelegate> delegateModal;

View File

@ -18,6 +18,13 @@
#import "DemoMessagesViewController.h"
#import "JSQCallCollectionViewCell.h"
#import "JSQCall.h"
#import "JSQDisplayedMessageCollectionViewCell.h"
#import "JSQErrorMessage.h"
#import "JSQInfoMessage.h"
@implementation DemoMessagesViewController
#pragma mark - View lifecycle
@ -43,7 +50,6 @@
self.senderId = kJSQDemoAvatarIdSquires;
self.senderDisplayName = kJSQDemoAvatarDisplayNameSquires;
self.inputToolbar.contentView.textView.pasteDelegate = self;
/**
* Load up our fake data for the demo
@ -68,30 +74,13 @@
style:UIBarButtonItemStyleBordered
target:self
action:@selector(receiveMessagePressed:)];
/**
* Register custom menu actions for cells.
*/
[JSQMessagesCollectionViewCell registerMenuAction:@selector(customAction:)];
/**
* OPT-IN: allow cells to be deleted
*/
[JSQMessagesCollectionViewCell registerMenuAction:@selector(delete:)];
/**
* Customize your toolbar buttons
*
* self.inputToolbar.contentView.leftBarButtonItem = custom button or nil to remove
* self.inputToolbar.contentView.rightBarButtonItem = custom button or nil to remove
*/
/**
* Set a maximum height for the input toolbar
*
* self.inputToolbar.maximumHeight = 150;
*/
}
- (void)viewWillAppear:(BOOL)animated
@ -119,19 +108,6 @@
#pragma mark - Custom menu actions for cells
- (void)didReceiveMenuWillShowNotification:(NSNotification *)notification
{
/**
* Display custom menu actions for cells.
*/
UIMenuController *menu = [notification object];
menu.menuItems = @[ [[UIMenuItem alloc] initWithTitle:@"Custom Action" action:@selector(customAction:)] ];
}
#pragma mark - Testing
- (void)pushMainViewController
@ -188,7 +164,7 @@
id<JSQMessageMediaData> newMediaData = nil;
id newMediaAttachmentCopy = nil;
if (copyMessage.isMediaMessage) {
if ([copyMessage isKindOfClass:[JSQMessage class]]) {
/**
* Last message was a media message
*/
@ -232,18 +208,6 @@
newMediaData = videoItemCopy;
}
else if ([copyMediaData isKindOfClass:[JSQAudioMediaItem class]]) {
JSQAudioMediaItem *audioItemCopy = [((JSQAudioMediaItem *)copyMediaData) copy];
audioItemCopy.appliesMediaViewMaskAsOutgoing = NO;
newMediaAttachmentCopy = [audioItemCopy.audioData copy];
/**
* Reset audio item to simulate "downloading" the audio
*/
audioItemCopy.audioData = nil;
newMediaData = audioItemCopy;
}
else {
NSLog(@"%s error: unrecognized media item", __PRETTY_FUNCTION__);
}
@ -300,10 +264,6 @@
((JSQVideoMediaItem *)newMediaData).isReadyToPlay = YES;
[self.collectionView reloadData];
}
else if ([newMediaData isKindOfClass:[JSQAudioMediaItem class]]) {
((JSQAudioMediaItem *)newMediaData).audioData = newMediaAttachmentCopy;
[self.collectionView reloadData];
}
else {
NSLog(@"%s error: unrecognized media item", __PRETTY_FUNCTION__);
}
@ -351,13 +311,11 @@
- (void)didPressAccessoryButton:(UIButton *)sender
{
[self.inputToolbar.contentView.textView resignFirstResponder];
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"Media messages"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@"Send photo", @"Send location", @"Send video", @"Send audio", nil];
otherButtonTitles:@"Send photo", @"Send location", @"Send video", nil];
[sheet showFromToolbar:self.inputToolbar];
}
@ -365,7 +323,6 @@
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == actionSheet.cancelButtonIndex) {
[self.inputToolbar.contentView.textView becomeFirstResponder];
return;
}
@ -387,10 +344,6 @@
case 2:
[self.demoData addVideoMediaMessage];
break;
case 3:
[self.demoData addAudioMediaMessage];
break;
}
[JSQSystemSoundPlayer jsq_playMessageSentSound];
@ -407,11 +360,6 @@
return [self.demoData.messages objectAtIndex:indexPath.item];
}
- (void)collectionView:(JSQMessagesCollectionView *)collectionView didDeleteMessageAtIndexPath:(NSIndexPath *)indexPath
{
[self.demoData.messages removeObjectAtIndex:indexPath.item];
}
- (id<JSQMessageBubbleImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView messageBubbleImageDataForItemAtIndexPath:(NSIndexPath *)indexPath
{
/**
@ -454,6 +402,8 @@
*/
JSQMessage *message = [self.demoData.messages objectAtIndex:indexPath.item];
if (![message isKindOfClass:[JSQCall class]] || ![message isKindOfClass:[JSQErrorMessage class]] || ![message isKindOfClass:[JSQInfoMessage class]]) return nil;
if ([message.senderId isEqualToString:self.senderId]) {
if (![NSUserDefaults outgoingAvatarSetting]) {
return nil;
@ -464,8 +414,7 @@
return nil;
}
}
return [self.demoData.avatars objectForKey:message.senderId];
}
@ -526,75 +475,34 @@
/**
* 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.isMediaMessage) {
if ([msg.senderId isEqualToString:self.senderId]) {
cell.textView.textColor = [UIColor blackColor];
}
else {
cell.textView.textColor = [UIColor whiteColor];
if ([msg isKindOfClass:[JSQMessage class]])
{
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
if (!msg.isMediaMessage) {
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) };
}
cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor,
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };
return cell;
} else if ([msg isKindOfClass:[JSQCall class]]) {
JSQCallCollectionViewCell *cell = (JSQCallCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
return cell;
} else {
JSQDisplayedMessageCollectionViewCell * cell = (JSQDisplayedMessageCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
return cell;
}
return cell;
}
#pragma mark - UICollectionView Delegate
#pragma mark - Custom menu items
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
if (action == @selector(customAction:)) {
return YES;
}
return [super collectionView:collectionView canPerformAction:action forItemAtIndexPath:indexPath withSender:sender];
}
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
if (action == @selector(customAction:)) {
[self customAction:sender];
return;
}
[super collectionView:collectionView performAction:action forItemAtIndexPath:indexPath withSender:sender];
}
- (void)customAction:(id)sender
{
NSLog(@"Custom action received! Sender: %@", sender);
[[[UIAlertView alloc] initWithTitle:@"Custom Action"
message:nil
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil]
show];
}
@ -616,9 +524,9 @@
*
* Show a timestamp for every 3rd message
*/
if (indexPath.item % 3 == 0) {
return kJSQMessagesCollectionViewCellLabelHeightDefault;
}
// if (indexPath.item % 3 == 0) {
// return kJSQMessagesCollectionViewCellLabelHeightDefault;
// }
return 0.0f;
}
@ -673,23 +581,4 @@
NSLog(@"Tapped cell at %@!", NSStringFromCGPoint(touchLocation));
}
#pragma mark - JSQMessagesComposerTextViewPasteDelegate methods
- (BOOL)composerTextView:(JSQMessagesComposerTextView *)textView shouldPasteWithSender:(id)sender
{
if ([UIPasteboard generalPasteboard].image) {
// If there's an image in the pasteboard, construct a media item with that image and `send` it.
JSQPhotoMediaItem *item = [[JSQPhotoMediaItem alloc] initWithImage:[UIPasteboard generalPasteboard].image];
JSQMessage *message = [[JSQMessage alloc] initWithSenderId:self.senderId
senderDisplayName:self.senderDisplayName
date:[NSDate date]
media:item];
[self.demoData.messages addObject:message];
[self finishSendingMessage];
return NO;
}
return YES;
}
@end

View File

@ -58,6 +58,4 @@ static NSString * const kJSQDemoAvatarIdWoz = @"309-41802-93823";
- (void)addVideoMediaMessage;
- (void)addAudioMediaMessage;
@end

View File

@ -20,6 +20,9 @@
#import "NSUserDefaults+DemoSettings.h"
#import "JSQCall.h"
#import "JSQInfoMessage.h"
#import "JSQErrorMessage.h"
/**
* This is for demo/testing purposes only.
@ -99,11 +102,18 @@
* You should have a mutable array or orderedSet, or something.
*/
self.messages = [[NSMutableArray alloc] initWithObjects:
[[JSQCall alloc] initWithCallerId:kJSQDemoAvatarIdWoz
callerDisplayName:kJSQDemoAvatarDisplayNameWoz
date:[NSDate date]
status:kCallOutgoing],
[[JSQMessage alloc] initWithSenderId:kJSQDemoAvatarIdSquires
senderDisplayName:kJSQDemoAvatarDisplayNameSquires
date:[NSDate distantPast]
text:@"Welcome to JSQMessages: A messaging UI framework for iOS."],
[[JSQMessage alloc] initWithSenderId:kJSQDemoAvatarIdSquires
senderDisplayName:kJSQDemoAvatarDisplayNameSquires
date:[NSDate distantPast]
text:@"Welcome to JSQMessages: A messaging UI framework for iOS."],
[[JSQMessage alloc] initWithSenderId:kJSQDemoAvatarIdWoz
senderDisplayName:kJSQDemoAvatarDisplayNameWoz
date:[NSDate distantPast]
@ -125,13 +135,45 @@
text:@"It is unit-tested, free, open-source, and documented."],
[[JSQMessage alloc] initWithSenderId:kJSQDemoAvatarIdSquires
senderDisplayName:kJSQDemoAvatarDisplayNameSquires
date:[NSDate date]
text:@"Now with media messages!"],
senderDisplayName:kJSQDemoAvatarDisplayNameSquires
date:[NSDate date]
text:@"Now with media messages!"],
[[JSQCall alloc] initWithCallerId:kJSQDemoAvatarIdWoz
callerDisplayName:kJSQDemoAvatarDisplayNameWoz
date:[NSDate date]
status:kCallIncoming],
[[JSQCall alloc] initWithCallerId:kJSQDemoAvatarIdWoz
callerDisplayName:kJSQDemoAvatarDisplayNameWoz
date:[NSDate date]
status:kCallMissed],
[[JSQInfoMessage alloc] initWithInfoType:JSQInfoMessageTypeSessionDidEnd
senderId:kJSQDemoAvatarIdCook
senderDisplayName:kJSQDemoAvatarDisplayNameCook
date:[NSDate date]],
[[JSQErrorMessage alloc] initWithErrorType:JSQErrorMessageMissingKeyId
senderId:kJSQDemoAvatarIdCook
senderDisplayName:kJSQDemoAvatarDisplayNameCook
date:[NSDate date]],
[[JSQErrorMessage alloc] initWithErrorType:JSQErrorMessageInvalidMessage
senderId:kJSQDemoAvatarIdCook
senderDisplayName:kJSQDemoAvatarDisplayNameCook
date:[NSDate date]],
[[JSQErrorMessage alloc] initWithErrorType:JSQErrorMessageInvalidVersion
senderId:kJSQDemoAvatarIdCook
senderDisplayName:kJSQDemoAvatarDisplayNameCook
date:[NSDate date]],
[[JSQErrorMessage alloc] initWithErrorType:JSQErrorMessageInvalidKeyException
senderId:kJSQDemoAvatarIdCook
senderDisplayName:kJSQDemoAvatarDisplayNameCook
date:[NSDate date]],
[[JSQErrorMessage alloc] initWithErrorType:JSQErrorMessageWrongTrustedIdentityKey
senderId:kJSQDemoAvatarIdCook
senderDisplayName:kJSQDemoAvatarDisplayNameCook
date:[NSDate date]],
nil];
[self addPhotoMediaMessage];
[self addAudioMediaMessage];
/**
* Setting to load extra messages for testing/demo
@ -157,17 +199,6 @@
}
}
- (void)addAudioMediaMessage
{
NSString * sample = [[NSBundle mainBundle] pathForResource:@"jsq_messages_sample" ofType:@"m4a"];
NSData * audioData = [NSData dataWithContentsOfFile:sample];
JSQAudioMediaItem *audioItem = [[JSQAudioMediaItem alloc] initWithData:audioData];
JSQMessage *audioMessage = [JSQMessage messageWithSenderId:kJSQDemoAvatarIdSquires
displayName:kJSQDemoAvatarDisplayNameSquires
media:audioItem];
[self.messages addObject:audioMessage];
}
- (void)addPhotoMediaMessage
{
JSQPhotoMediaItem *photoItem = [[JSQPhotoMediaItem alloc] initWithImage:[UIImage imageNamed:@"goldengate"]];

View File

@ -71,12 +71,6 @@
"idiom" : "ipad",
"filename" : "Icon-76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "icon167.png",
"scale" : "2x"
}
],
"info" : {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<string>com.hexedbits.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@ -15,11 +15,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>7.3.4</string>
<string>6.1.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>7.3.4</string>
<string>6.1.1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>

View File

@ -38,23 +38,16 @@
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 4;
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch (section) {
case 0:
return 2;
case 1:
return 2;
case 2:
return 1;
case 3:
return 1;
default:
return 0;
if (section == 2) {
return 1;
}
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
@ -65,7 +58,7 @@
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if (indexPath.section == 0) {
switch (indexPath.row) {
case 0:
@ -93,14 +86,7 @@
break;
}
}
else if (indexPath.section == 3) {
switch (indexPath.row) {
case 0:
cell.textLabel.text = @"Push view 2 levels";
break;
}
}
return cell;
}
@ -111,8 +97,6 @@
return @"Presentation";
case 2:
return @"Demo options";
case 3:
return @"Other testing";
default:
return nil;
}
@ -120,7 +104,7 @@
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
return (section == 2) ? @"Copyright © 2015\nJesse Squires\nMIT License" : nil;
return (section == [tableView numberOfSections] - 1) ? @"Copyright © 2014\nJesse Squires\nMIT License" : nil;
}
#pragma mark - Table view delegate
@ -162,19 +146,6 @@
break;
}
}
else if (indexPath.section == 3) {
switch (indexPath.row) {
case 0:
{
UIViewController *blank = [[UIViewController alloc] initWithNibName:nil bundle:nil];
blank.title = @"Blank";
blank.view.backgroundColor = [UIColor lightGrayColor];
[self.navigationController pushViewController:blank animated:NO];
DemoMessagesViewController *vc = [DemoMessagesViewController messagesViewController];
[self.navigationController pushViewController:vc animated:YES];
}
}
}
}
#pragma mark - Segues

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,46 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// MIT License
// Copyright (c) 2014 Jesse Squires
// http://opensource.org/licenses/MIT
//
#import <XCTest/XCTest.h>
#import "NSBundle+JSQMessages.h"
@interface JSQMessagesNSBundleTests : XCTestCase
@end
@implementation JSQMessagesNSBundleTests
- (void)testMessagesBundle
{
XCTAssertNotNil([NSBundle jsq_messagesBundle]);
}
- (void)testAssetBundle
{
NSBundle *bundle = [NSBundle jsq_messagesAssetBundle];
XCTAssertNotNil(bundle);
XCTAssertEqualObjects(bundle.bundlePath.lastPathComponent, @"JSQMessagesAssets.bundle");
}
- (void)testLocalizedStringForKey
{
XCTAssertNotNil([NSBundle jsq_localizedStringForKey:@"send"]);
XCTAssertNotEqualObjects([NSBundle jsq_localizedStringForKey:@"send"], @"send");
XCTAssertNotNil([NSBundle jsq_localizedStringForKey:@"load_earlier_messages"]);
XCTAssertNotEqualObjects([NSBundle jsq_localizedStringForKey:@"load_earlier_messages"], @"load_earlier_messages");
XCTAssertNotNil([NSBundle jsq_localizedStringForKey:@"new_message"]);
XCTAssertNotEqualObjects([NSBundle jsq_localizedStringForKey:@"new_message"], @"new_message");
}
@end

View File

@ -10,6 +10,8 @@
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import "JSQMessagesViewController.h"
#import "DemoMessagesViewController.h"
@ -46,17 +48,14 @@
XCTAssertNotNil(nib, @"Nib should not be nil");
JSQMessagesViewController *vc = [JSQMessagesViewController messagesViewController];
vc.senderId = @"senderId";
vc.senderDisplayName = @"senderDisplayName";
[vc beginAppearanceTransition:YES animated:NO];
[vc endAppearanceTransition];
[vc view];
XCTAssertNotNil(vc, @"View controller should not be nil");
XCTAssertNotNil(vc.view, @"View should not be nil");
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");
XCTAssertEqual(vc.automaticallyAdjustsScrollViewInsets, YES, @"Property should be equal to default value");
XCTAssertEqualObjects(vc.incomingCellIdentifier, [JSQMessagesCollectionViewCellIncoming cellReuseIdentifier], @"Property should be equal to default value");
@ -69,12 +68,7 @@
- (void)testJSQMessagesViewControllerSubclassInitProgramatically
{
DemoMessagesViewController *demoVC = [DemoMessagesViewController messagesViewController];
demoVC.senderId = @"senderId";
demoVC.senderDisplayName = @"senderDisplayName";
[demoVC beginAppearanceTransition:YES animated:NO];
[demoVC endAppearanceTransition];
[demoVC view];
XCTAssertNotNil(demoVC, @"View controller should not be nil");
XCTAssertTrue([demoVC isKindOfClass:[DemoMessagesViewController class]], @"View controller should be kind of class: %@", [DemoMessagesViewController class]);
XCTAssertNotNil(demoVC.view, @"View should not be nil");
@ -88,12 +82,7 @@
XCTAssertNotNil(mainSB, @"Storyboard should not be nil");
DemoMessagesViewController *demoVC = [mainSB instantiateViewControllerWithIdentifier:@"DemoVC"];
demoVC.senderId = @"senderId";
demoVC.senderDisplayName = @"senderDisplayName";
[demoVC beginAppearanceTransition:YES animated:NO];
[demoVC endAppearanceTransition];
[demoVC view];
XCTAssertNotNil(demoVC, @"View controller should not be nil");
XCTAssertTrue([demoVC isKindOfClass:[DemoMessagesViewController class]], @"View controller should be kind of class: %@", [DemoMessagesViewController class]);
XCTAssertNotNil(demoVC.view, @"View should not be nil");
@ -101,4 +90,14 @@
XCTAssertNotNil(demoVC.inputToolbar, @"Input toolbar should not be nil");
}
- (void)testViewConfiguration
{
JSQMessagesViewController *vc = [JSQMessagesViewController messagesViewController];
id mockVC = [OCMockObject partialMockForObject:vc];
[[mockVC expect] jsq_configureMessagesViewController];
[vc view];
[mockVC verify];
}
@end

View File

@ -98,7 +98,7 @@
NSString *relativeDateString = [[JSQMessagesTimestampFormatter sharedFormatter] relativeDateForDate:date];
XCTAssertEqualObjects(relativeDateString, @"Today", @"Relative date string should return expected value");
XCTAssertEqualObjects(relativeDateString, @"Today", @"Relative date string shoudl return expected value");
}
@end

View File

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<string>com.hexedbits.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>

View File

@ -1,77 +0,0 @@
//
// Created by Jesse Squires
// http://www.jessesquires.com
//
//
// MIT License
// Copyright (c) 2014 Jesse Squires
// http://opensource.org/licenses/MIT
//
#import <XCTest/XCTest.h>
#import "JSQAudioMediaItem.h"
@interface JSQAudioMediaItemTests : XCTestCase
@end
@implementation JSQAudioMediaItemTests
- (void)setUp
{
[super setUp];
}
- (void)tearDown
{
[super tearDown];
}
- (void)testAudioItemInit
{
JSQAudioMediaItem *item = [[JSQAudioMediaItem alloc] initWithData:[NSData data]];
XCTAssertNotNil(item);
}
- (void)testAudioItemIsEqual
{
NSString * sample = [[NSBundle mainBundle] pathForResource:@"jsq_messages_sample" ofType:@"m4a"];
JSQAudioMediaItem *item = [[JSQAudioMediaItem alloc] initWithData:[NSData dataWithContentsOfFile:sample]];
JSQAudioMediaItem *copy = [item copy];
XCTAssertEqualObjects(item, copy, @"Copied items should be equal");
XCTAssertEqual([item hash], [copy hash], @"Copied item hashes should be equal");
XCTAssertEqualObjects(item, item, @"Item should be equal to itself");
}
- (void)testAudioItemArchiving
{
NSString * sample = [[NSBundle mainBundle] pathForResource:@"jsq_messages_sample" ofType:@"m4a"];
JSQAudioMediaItem *item = [[JSQAudioMediaItem alloc] initWithData:[NSData dataWithContentsOfFile:sample]];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:item];
JSQAudioMediaItem *unarchivedItem = [NSKeyedUnarchiver unarchiveObjectWithData:data];
XCTAssertEqualObjects(item, unarchivedItem);
}
- (void)testMediaDataProtocol
{
JSQAudioMediaItem *item = [[JSQAudioMediaItem alloc] init];
XCTAssertTrue(!CGSizeEqualToSize([item mediaViewDisplaySize], CGSizeZero));
XCTAssertNotNil([item mediaPlaceholderView]);
XCTAssertNil([item mediaView], @"Media view should be nil if image is nil");
NSString * sample = [[NSBundle mainBundle] pathForResource:@"jsq_messages_sample" ofType:@"m4a"];
item.audioData = [NSData dataWithContentsOfFile:sample];
XCTAssertNotNil([item mediaView], @"Media view should NOT be nil once item has media data");
}
@end

View File

@ -54,7 +54,7 @@
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:15 handler:^(NSError *error) {
[self waitForExpectationsWithTimeout:5 handler:^(NSError *error) {
XCTAssertNil(error, @"Expectation should not error");
}];

View File

@ -10,7 +10,7 @@
#import <XCTest/XCTest.h>
//#import <OCMock/OCMock.h>
#import <OCMock/OCMock.h>
#import "JSQMessage.h"
@ -30,10 +30,6 @@
- (BOOL)isEqual:(id)object { return YES; }
- (NSUInteger)hash { return 10000; }
- (NSUInteger)mediaHash { return self.hash; }
@end
@ -44,7 +40,7 @@
@property (strong, nonatomic) NSString *senderId;
@property (strong, nonatomic) NSString *senderDisplayName;
@property (strong, nonatomic) NSDate *date;
@property (strong, nonatomic) FakeMedia *fakeMediaData;
@property (strong, nonatomic) id<JSQMessageMediaData> mockMediaData;
@end
@ -57,7 +53,7 @@
self.senderId = @"324543-43556-212343";
self.senderDisplayName = @"Jesse Squires";
self.date = [NSDate date];
self.fakeMediaData = [FakeMedia new];
self.mockMediaData = [OCMockObject mockForProtocol:@protocol(JSQMessageMediaData)];
}
- (void)tearDown
@ -65,7 +61,7 @@
self.senderId = nil;
self.senderDisplayName = nil;
self.date = nil;
self.fakeMediaData = nil;
self.mockMediaData = nil;
[super tearDown];
}
@ -74,12 +70,13 @@
JSQMessage *msg = [[JSQMessage alloc] initWithSenderId:self.senderId
senderDisplayName:self.senderDisplayName
date:self.date
media:self.fakeMediaData];
media:self.mockMediaData];
XCTAssertNotNil(msg, @"Message should not be nil");
}
- (void)testMediaMessageInvalidInit
{
XCTAssertThrows([[JSQMessage alloc] init], @"Invalid init should throw");
XCTAssertThrows([[JSQMessage alloc] initWithSenderId:nil senderDisplayName:nil date:nil media:nil], @"Invalid init should throw");
}
@ -88,7 +85,7 @@
JSQMessage *msg = [[JSQMessage alloc] initWithSenderId:self.senderId
senderDisplayName:self.senderDisplayName
date:self.date
media:self.fakeMediaData];
media:self.mockMediaData];
JSQMessage *copy = [msg copy];
XCTAssertEqualObjects(msg, copy, @"Copied messages should be equal");

View File

@ -60,6 +60,7 @@
- (void)testTextMessageInvalidInit
{
XCTAssertThrows([[JSQMessage alloc] init], @"Invalid init should throw");
XCTAssertThrows([[JSQMessage alloc] initWithSenderId:nil senderDisplayName:nil date:nil text:nil], @"Invalid init should throw");
}

View File

@ -32,6 +32,7 @@
- (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");
}

View File

@ -34,6 +34,7 @@
- (void)testInitInvalid
{
XCTAssertThrows([[JSQMessagesBubbleImage alloc] init], @"Invalid init should throw");
XCTAssertThrows([[JSQMessagesBubbleImage alloc] initWithMessageBubbleImage:nil highlightedImage:nil], @"Invalid init should throw");
}

View File

@ -39,7 +39,7 @@
XCTAssertNotNil(view, @"Collection view should not be nil");
XCTAssertEqualObjects(view.backgroundColor, [UIColor whiteColor], @"Property should be equal to default value");
XCTAssertEqual(view.keyboardDismissMode, UIScrollViewKeyboardDismissModeNone, @"Property should be equal to default value");
XCTAssertEqual(view.keyboardDismissMode, UIScrollViewKeyboardDismissModeInteractive, @"Property should be equal to default value");
XCTAssertEqual(view.alwaysBounceVertical, YES, @"Property should be equal to default value");
XCTAssertEqual(view.bounces, YES, @"Property should be equal to default value");
}

View File

@ -12,7 +12,6 @@
#import "JSQMessagesViewController.h"
#import "JSQMessagesInputToolbar.h"
#import "DemoMessagesViewController.h"
@interface JSQMessagesInputToolbarTests : XCTestCase
@ -35,36 +34,11 @@
{
JSQMessagesViewController *vc = [JSQMessagesViewController messagesViewController];
[vc loadView];
JSQMessagesInputToolbar *toolbar = vc.inputToolbar;
XCTAssertNotNil(toolbar, @"Toolbar should not be nil");
XCTAssertNotNil(toolbar.contentView, @"Toolbar content view should not be nil");
XCTAssertEqual(toolbar.sendButtonOnRight, YES, @"Property should be equal to default value");
}
- (void)testSetMaximumHeight
{
UIStoryboard *mainSB = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
XCTAssertNotNil(mainSB, @"Storyboard should not be nil");
DemoMessagesViewController *demoVC = [mainSB instantiateViewControllerWithIdentifier:@"DemoVC"];
[demoVC beginAppearanceTransition:YES animated:NO];
[demoVC endAppearanceTransition];
XCTAssertEqual(demoVC.inputToolbar.maximumHeight, NSNotFound, @"maximumInputToolbarHeight should equal default value");
demoVC.inputToolbar.maximumHeight = 54;
CGRect newBounds = demoVC.inputToolbar.bounds;
newBounds.size.height = 100;
demoVC.inputToolbar.bounds = newBounds;
XCTAssertEqual(CGRectGetHeight(demoVC.inputToolbar.bounds), 100);
[demoVC.view setNeedsUpdateConstraints];
[demoVC.view setNeedsLayout];
[demoVC.view layoutIfNeeded];
XCTAssertLessThanOrEqual(CGRectGetHeight(demoVC.inputToolbar.frame), 54, @"Toolbar height should be <= to maximumInputToolbarHeight");
}
@end

View File

@ -1,26 +1,21 @@
Pod::Spec.new do |s|
s.name = 'JSQMessagesViewController'
s.version = '7.3.4'
s.summary = 'An elegant messages UI library for iOS.'
s.homepage = 'http://jessesquires.github.io/JSQMessagesViewController'
s.license = 'MIT'
s.platform = :ios, '7.0'
s.name = 'JSQMessagesViewController'
s.version = '6.1.1'
s.summary = 'An elegant messages UI library for iOS.'
s.homepage = 'http://jessesquires.github.io/JSQMessagesViewController'
s.license = 'MIT'
s.screenshots = ['https://raw.githubusercontent.com/jessesquires/JSQMessagesViewController/develop/Screenshots/screenshot0.png',
'https://raw.githubusercontent.com/jessesquires/JSQMessagesViewController/develop/Screenshots/screenshot1.png',
'https://raw.githubusercontent.com/jessesquires/JSQMessagesViewController/develop/Screenshots/screenshot2.png',
'https://raw.githubusercontent.com/jessesquires/JSQMessagesViewController/develop/Screenshots/screenshot3.png']
s.author = { 'Jesse Squires' => 'jesse.squires.developer@gmail.com' }
s.social_media_url = 'https://twitter.com/jesse_squires'
s.source = { :git => 'https://github.com/jessesquires/JSQMessagesViewController.git', :tag => s.version.to_s }
s.platform = :ios, '7.0'
s.source_files = 'JSQMessagesViewController/**/*.{h,m}'
s.resources = 'JSQMessagesViewController/Assets/JSQMessagesAssets.bundle', 'JSQMessagesViewController/Assets/Strings/*.lproj', 'JSQMessagesViewController/**/*.{xib}',
s.frameworks = 'QuartzCore', 'CoreGraphics', 'CoreLocation', 'MapKit', 'UIKit', 'Foundation'
s.requires_arc = true
s.author = 'Jesse Squires'
s.social_media_url = 'https://twitter.com/jesse_squires'
s.screenshots = ['https://raw.githubusercontent.com/jessesquires/JSQMessagesViewController/develop/Screenshots/screenshot0.png',
'https://raw.githubusercontent.com/jessesquires/JSQMessagesViewController/develop/Screenshots/screenshot1.png',
'https://raw.githubusercontent.com/jessesquires/JSQMessagesViewController/develop/Screenshots/screenshot2.png',
'https://raw.githubusercontent.com/jessesquires/JSQMessagesViewController/develop/Screenshots/screenshot3.png']
s.source = { :git => 'https://github.com/jessesquires/JSQMessagesViewController.git', :tag => s.version }
s.source_files = 'JSQMessagesViewController/**/*.{h,m}'
s.resources = ['JSQMessagesViewController/Assets/JSQMessagesAssets.bundle', 'JSQMessagesViewController/**/*.{xib}']
s.frameworks = 'QuartzCore', 'CoreGraphics', 'CoreLocation', 'MapKit', 'AVFoundation'
s.requires_arc = true
s.dependency 'JSQSystemSoundPlayer', '~> 2.0.1'
s.dependency 'JSQSystemSoundPlayer', '~> 2.0.0'
end

View File

@ -1,37 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Load Earlier Messages";
"send" = "Send";
"new_message" = "New Message";
"text_message_accessibility_label" = "%@: %@";
"media_message_accessibility_label" = "%@: media message";
"accessory_button_accessibility_label" = "Share media";
"new_message_received_accessibility_announcement" = "New message received";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -1,29 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "تحميل الرسائل السابقة";
"send" = "أرسال";
"new_message" = "رسالة جديدة";

View File

@ -1,37 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Ältere Nachrichten laden";
"send" = "Senden";
"new_message" = "Neue Nachricht";
"text_message_accessibility_label" = "%@: %@";
"media_message_accessibility_label" = "%@: media Nachricht";
"accessory_button_accessibility_label" = "Aktien media";
"new_message_received_accessibility_announcement" = "Neue Nachricht empfangen";

View File

@ -1,37 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Load Earlier Messages";
"send" = "Send";
"new_message" = "New Message";
"text_message_accessibility_label" = "%@: %@";
"media_message_accessibility_label" = "%@: media message";
"accessory_button_accessibility_label" = "Share media";
"new_message_received_accessibility_announcement" = "New message received";

View File

@ -1,37 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Cargar mensajes anteriores";
"send" = "Enviar";
"new_message" = "Nuevo mensaje";
"text_message_accessibility_label" = "%@: %@";
"media_message_accessibility_label" = "%@: imagen";
"accessory_button_accessibility_label" = "Intercambio de archivos";
"new_message_received_accessibility_announcement" = "mensaje recibido";

View File

@ -1,37 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Messages précedents";
"send" = "Envoyer";
"new_message" = "Nouveau message";
"text_message_accessibility_label" = "%@: %@";
"media_message_accessibility_label" = "%@: image";
"accessory_button_accessibility_label" = "Partager fichier";
"new_message_received_accessibility_announcement" = "Nouveau message reçu";

View File

@ -1,29 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "古いメッセージを読み込む";
"send" = "送信";
"new_message" = "新しいメッセージ";

View File

@ -1,29 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "이전 메시지 불러오기";
"send" = "전송";
"new_message" = "새로운 메시지";

View File

@ -1,37 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Last tidligere beskjeder";
"send" = "Send";
"new_message" = "Ny melding";
"text_message_accessibility_label" = "%@: %@";
"media_message_accessibility_label" = "%@: mediamelding";
"accessory_button_accessibility_label" = "Del media";
"new_message_received_accessibility_announcement" = "Ny melding mottatt";

View File

@ -1,29 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Otwórz wcześniejsze wiadomości";
"send" = "Wyślij";
"new_message" = "Nowa wiadomość";

View File

@ -1,29 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Carregar mensagens anteriores";
"send" = "Enviar";
"new_message" = "Nova Mensagem";

View File

@ -1,29 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Încărcați mesajele anterioare";
"send" = "Trimiteți";
"new_message" = "Mesaj nou";

View File

@ -1,29 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "โหลดข้อความก่อนหน้า";
"send" = "ส่ง";
"new_message" = "ข้อความใหม่";

View File

@ -1,29 +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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Tải thêm tin nhắn";
"send" = "Gửi";
"new_message" = "Tin nhắn mới";

View File

@ -22,8 +22,8 @@
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Muat Pesan Sebelumnya";
"Load Earlier Messages" = "Load Earlier Messages";
"send" = "Kirim";
"Send" = "Send";
"new_message" = "Pesan Baru";
"New Message" = "New Message";

View File

@ -22,8 +22,8 @@
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Lataa aiempia viestejä";
"Load Earlier Messages" = "Ältere Nachrichten laden";
"send" = "Lähetä";
"Send" = "Senden";
"new_message" = "Uusi viesti";
"New Message" = "Neue Nachricht";

View File

@ -22,8 +22,8 @@
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "载入较早的信息";
"Load Earlier Messages" = "Load Earlier Messages";
"send" = "发送";
"Send" = "Send";
"new_message" = "新信息";
"New Message" = "New Message";

View File

@ -0,0 +1,29 @@
//
// 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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"Load Earlier Messages" = "Cargar mensajes anteriores";
"Send" = "Enviar";
"New Message" = "Nuevo mensaje";

View File

@ -22,8 +22,8 @@
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Laad eerdere berichten";
"Load Earlier Messages" = "Messages précedents";
"send" = "Stuur";
"Send" = "Envoi";
"new_message" = "Nieuw bericht";
"New Message" = "Nouveau message";

View File

@ -22,8 +22,8 @@
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "טען הודעות קודמות";
"Load Earlier Messages" = "טען הודעות קודמות";
"send" = "שלח";
"Send" = "שלח";
"new_message" = "הודעה חדשה";
"New Message" = "הודעה חדשה";

View File

@ -22,8 +22,8 @@
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Carica messaggi precedenti";
"Load Earlier Messages" = "Carica messaggi precedenti";
"send" = "Invia";
"Send" = "Invia";
"new_message" = "Nuovo Messaggio";
"New Message" = "Nuovo Messaggio";

View File

@ -22,8 +22,8 @@
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Učitaj ranije poruke";
"Load Earlier Messages" = "Laad eerdere berichten";
"send" = "Šalji";
"Send" = "Stuur";
"new_message" = "Nova poruka";
"New Message" = "Nieuw bericht";

View File

@ -0,0 +1,29 @@
//
// 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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"Load Earlier Messages" = "Otwórz wcześniejsze wiadomości";
"Send" = "Wyślij";
"New Message" = "Nowa wiadomość";

View File

@ -0,0 +1,29 @@
//
// 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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"Load Earlier Messages" = "Carregar mensagens anteriore";
"Send" = "Enviar";
"New Message" = "Nova Mensagem";

View File

@ -0,0 +1,29 @@
//
// 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
//
// ********************************
// Special thanks to the localization contributors!
//
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"Load Earlier Messages" = "Încărcați mesajele anterioare";
"Send" = "Trimiteți";
"New Message" = "Mesaj nou";

View File

@ -22,8 +22,8 @@
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Предыдущие сообщения";
"Load Earlier Messages" = "Предыдущие сообщения";
"send" = "Отпр";
"Send" = "Отпр";
"new_message" = "Сообщение";
"New Message" = "Сообщение";

View File

@ -22,8 +22,8 @@
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Eski mesajları yükle";
"Load Earlier Messages" = "Eski mesajları yükle";
"send" = "Gönder";
"Send" = "Gönder";
"new_message" = "Yeni Mesaj";
"New Message" = "Yeni Mesaj";

View File

@ -22,8 +22,8 @@
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "載入之前的訊息";
"Load Earlier Messages" = "载入较早的信息";
"send" = "傳送";
"Send" = "发送";
"new_message" = "新信息";
"New Message" = "新信息";

View File

@ -22,8 +22,8 @@
// https://github.com/jessesquires/JSQMessagesViewController/issues/237
// ********************************
"load_earlier_messages" = "Muat Turun Mesej Lama";
"Load Earlier Messages" = "載入之前的訊息";
"send" = "Hantar";
"Send" = "傳送";
"new_message" = "Mesej Baru";
"New Message" = "新信息";

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

@ -18,58 +18,34 @@
#import "JSQSystemSoundPlayer+JSQMessages.h"
#import "NSBundle+JSQMessages.h"
static NSString * const kJSQMessageReceivedSoundName = @"message_received";
static NSString * const kJSQMessageSentSoundName = @"message_sent";
static NSString * const kJSQMessageReceivedSoundName = @"JSQMessagesAssets.bundle/Sounds/message_received";
static NSString * const kJSQMessageSentSoundName = @"JSQMessagesAssets.bundle/Sounds/message_sent";
@implementation JSQSystemSoundPlayer (JSQMessages)
#pragma mark - Public
+ (void)jsq_playMessageReceivedSound
{
[self jsq_playSoundFromJSQMessagesBundleWithName:kJSQMessageReceivedSoundName asAlert:NO];
[[JSQSystemSoundPlayer sharedPlayer] playSoundWithFilename:kJSQMessageReceivedSoundName
fileExtension:kJSQSystemSoundTypeAIFF];
}
+ (void)jsq_playMessageReceivedAlert
{
[self jsq_playSoundFromJSQMessagesBundleWithName:kJSQMessageReceivedSoundName asAlert:YES];
[[JSQSystemSoundPlayer sharedPlayer] playAlertSoundWithFilename:kJSQMessageReceivedSoundName
fileExtension:kJSQSystemSoundTypeAIFF];
}
+ (void)jsq_playMessageSentSound
{
[self jsq_playSoundFromJSQMessagesBundleWithName:kJSQMessageSentSoundName asAlert:NO];
[[JSQSystemSoundPlayer sharedPlayer] playSoundWithFilename:kJSQMessageSentSoundName
fileExtension:kJSQSystemSoundTypeAIFF];
}
+ (void)jsq_playMessageSentAlert
{
[self jsq_playSoundFromJSQMessagesBundleWithName:kJSQMessageSentSoundName asAlert:YES];
}
#pragma mark - Private
+ (void)jsq_playSoundFromJSQMessagesBundleWithName:(NSString *)soundName asAlert:(BOOL)asAlert
{
// save sound player original bundle
NSString *originalPlayerBundleIdentifier = [JSQSystemSoundPlayer sharedPlayer].bundle.bundleIdentifier;
// search for sounds in this library's bundle
[JSQSystemSoundPlayer sharedPlayer].bundle = [NSBundle jsq_messagesBundle];
NSString *fileName = [NSString stringWithFormat:@"JSQMessagesAssets.bundle/Sounds/%@", soundName];
if (asAlert) {
[[JSQSystemSoundPlayer sharedPlayer] playAlertSoundWithFilename:fileName fileExtension:kJSQSystemSoundTypeAIFF];
}
else {
[[JSQSystemSoundPlayer sharedPlayer] playSoundWithFilename:fileName fileExtension:kJSQSystemSoundTypeAIFF];
}
// restore original bundle
[JSQSystemSoundPlayer sharedPlayer].bundle = [NSBundle bundleWithIdentifier:originalPlayerBundleIdentifier];
[[JSQSystemSoundPlayer sharedPlayer] playAlertSoundWithFilename:kJSQMessageSentSoundName
fileExtension:kJSQSystemSoundTypeAIFF];
}
@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/Foundation.h>
@interface NSBundle (JSQMessages)
/**
* @return The bundle for JSQMessagesViewController.
*/
+ (NSBundle *)jsq_messagesBundle;
/**
* @return The bundle for assets in JSQMessagesViewController.
*/
+ (NSBundle *)jsq_messagesAssetBundle;
/**
* Returns a localized version of the string designated by the specified key and residing in the JSQMessages table.
*
* @param key The key for a string in the JSQMessages table.
*
* @return A localized version of the string designated by key in the JSQMessages table.
*/
+ (NSString *)jsq_localizedStringForKey:(NSString *)key;
@end

View File

@ -1,44 +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 "NSBundle+JSQMessages.h"
#import "JSQMessagesViewController.h"
@implementation NSBundle (JSQMessages)
+ (NSBundle *)jsq_messagesBundle
{
return [NSBundle bundleForClass:[JSQMessagesViewController class]];
}
+ (NSBundle *)jsq_messagesAssetBundle
{
NSString *bundleResourcePath = [NSBundle jsq_messagesBundle].resourcePath;
NSString *assetPath = [bundleResourcePath stringByAppendingPathComponent:@"JSQMessagesAssets.bundle"];
return [NSBundle bundleWithPath:assetPath];
}
+ (NSString *)jsq_localizedStringForKey:(NSString *)key
{
// In Signal, we prefer to use our own translations to the incomplete translations in this bundle
// return NSLocalizedStringFromTableInBundle(key, @"JSQMessages", [NSBundle jsq_messagesAssetBundle], nil);
return NSLocalizedString(key, nil);
}
@end

View File

@ -42,6 +42,22 @@
*/
+ (UIColor *)jsq_messageBubbleLightGrayColor;
/**
* @return A color object containing HSB values similar to Signal gray bubble color.
*/
+ (UIColor *)jsq_messageBubbleGrayColor;
/**
* @return A color object containing HSB values similar to Signal light blue bubble color.
*/
+ (UIColor *)jsq_messageBubbleLightBlueColor;
/**
* @return A color object containing HSB values similar to Signal background gray color.
*/
+ (UIColor *)jsq_messageBackgroundGrayColor;
#pragma mark - Utilities
/**

View File

@ -54,6 +54,23 @@
alpha:1.0f];
}
+ (UIColor *)jsq_messageBubbleLightBlueColor
{
return [UIColor colorWithRed:137/255.f green:214/255.f blue:250/255.f alpha:1];
}
+ (UIColor *)jsq_messageBubbleGrayColor
{
return [UIColor colorWithRed:230/255.f green:230/255.f blue:230/255.f alpha:1];
}
+ (UIColor *)jsq_messageBackgroundGrayColor
{
return [UIColor colorWithRed:242.f/255 green:242.f/255 blue:242.f/255 alpha:1];
}
#pragma mark - Utilities
- (UIColor *)jsq_colorByDarkeningColorWithValue:(CGFloat)value

View File

@ -25,9 +25,4 @@
*/
+ (BOOL)jsq_isCurrentDeviceBeforeiOS8;
/**
* @return Whether or not the current device is running a version of iOS after 9.0.
*/
+ (BOOL)jsq_isCurrentDeviceAfteriOS9;
@end

View File

@ -23,13 +23,7 @@
+ (BOOL)jsq_isCurrentDeviceBeforeiOS8
{
// iOS < 8.0
return [[UIDevice currentDevice].systemVersion compare:@"8.0" options:NSNumericSearch] == NSOrderedAscending;
}
+ (BOOL)jsq_isCurrentDeviceAfteriOS9
{
// iOS > 9.0
return [[UIDevice currentDevice].systemVersion compare:@"9.0" options:NSNumericSearch] == NSOrderedDescending;
return [[UIDevice currentDevice].systemVersion compare:@"8.0.0" options:NSNumericSearch] == NSOrderedAscending;
}
@end

View File

@ -52,7 +52,7 @@
/**
* @return The compact message bubble image.
*
* @discussion This is the default bubble image used by `JSQMessagesBubbleImageFactory`.
* @disscussion This is the default bubble image used by `JSQMessagesBubbleImageFactory`.
*/
+ (UIImage *)jsq_bubbleCompactImage;
@ -76,9 +76,4 @@
*/
+ (UIImage *)jsq_defaultPlayImage;
/**
* @return The default pause icon image.
*/
+ (UIImage *)jsq_defaultPauseImage;
@end

View File

@ -18,9 +18,6 @@
#import "UIImage+JSQMessages.h"
#import "NSBundle+JSQMessages.h"
@implementation UIImage (JSQMessages)
- (UIImage *)jsq_imageMaskedWithColor:(UIColor *)maskColor
@ -50,9 +47,7 @@
+ (UIImage *)jsq_bubbleImageFromBundleWithName:(NSString *)name
{
NSBundle *bundle = [NSBundle jsq_messagesAssetBundle];
NSString *path = [bundle pathForResource:name ofType:@"png" inDirectory:@"Images"];
return [UIImage imageWithContentsOfFile:path];
return [UIImage imageNamed:[NSString stringWithFormat:@"JSQMessagesAssets.bundle/Images/%@", name]];
}
+ (UIImage *)jsq_bubbleRegularImage
@ -100,9 +95,5 @@
return [UIImage jsq_bubbleImageFromBundleWithName:@"play"];
}
+ (UIImage *)jsq_defaultPauseImage
{
return [UIImage jsq_bubbleImageFromBundleWithName:@"pause"];
}
@end

View File

@ -59,6 +59,13 @@ FOUNDATION_EXPORT NSString * const JSQMessagesKeyboardControllerUserInfoKeyKeybo
*/
- (void)keyboardController:(JSQMessagesKeyboardController *)keyboardController keyboardDidChangeFrame:(CGRect)keyboardFrame;
/**
* Tells the delegate that the keyboard has been hidden.
*
* @param keyboardController The keyboard controller that is notifying the delegate.
*/
- (void)keyboardControllerKeyboardDidHide:(JSQMessagesKeyboardController *)keyboardController;
@end
@ -110,11 +117,6 @@ FOUNDATION_EXPORT NSString * const JSQMessagesKeyboardControllerUserInfoKeyKeybo
*/
@property (assign, nonatomic, readonly) CGRect currentKeyboardFrame;
/**
* Not a valid initializer.
*/
- (id)init NS_UNAVAILABLE;
/**
* Creates a new keyboard controller object with the specified textView, contextView, panGestureRecognizer, and delegate.
*
@ -128,7 +130,7 @@ FOUNDATION_EXPORT NSString * const JSQMessagesKeyboardControllerUserInfoKeyKeybo
- (instancetype)initWithTextView:(UITextView *)textView
contextView:(UIView *)contextView
panGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer
delegate:(id<JSQMessagesKeyboardControllerDelegate>)delegate NS_DESIGNATED_INITIALIZER;
delegate:(id<JSQMessagesKeyboardControllerDelegate>)delegate;
/**
* Tells the keyboard controller that it should begin listening for system keyboard notifications.

View File

@ -39,7 +39,24 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
@property (assign, nonatomic) BOOL jsq_isObserving;
@property (strong, nonatomic) UIView *keyboardView;
@property (weak, nonatomic) UIView *keyboardView;
- (void)jsq_registerForNotifications;
- (void)jsq_unregisterForNotifications;
- (void)jsq_didReceiveKeyboardDidShowNotification:(NSNotification *)notification;
- (void)jsq_didReceiveKeyboardWillChangeFrameNotification:(NSNotification *)notification;
- (void)jsq_didReceiveKeyboardDidChangeFrameNotification:(NSNotification *)notification;
- (void)jsq_didReceiveKeyboardDidHideNotification:(NSNotification *)notification;
- (void)jsq_handleKeyboardNotification:(NSNotification *)notification completion:(JSQAnimationCompletionBlock)completion;
- (void)jsq_setKeyboardViewHidden:(BOOL)hidden;
- (void)jsq_notifyKeyboardFrameNotificationForFrame:(CGRect)frame;
- (void)jsq_removeKeyboardFrameObserver;
- (void)jsq_handlePanGestureRecognizer:(UIPanGestureRecognizer *)pan;
@end
@ -58,7 +75,7 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
NSParameterAssert(textView != nil);
NSParameterAssert(contextView != nil);
NSParameterAssert(panGestureRecognizer != nil);
self = [super init];
if (self) {
_textView = textView;
@ -74,8 +91,11 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
{
[self jsq_removeKeyboardFrameObserver];
[self jsq_unregisterForNotifications];
_textView = nil;
_contextView = nil;
_panGestureRecognizer = nil;
_delegate = nil;
_keyboardView = nil;
}
#pragma mark - Setters
@ -85,15 +105,15 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
if (_keyboardView) {
[self jsq_removeKeyboardFrameObserver];
}
_keyboardView = keyboardView;
if (keyboardView && !_jsq_isObserving) {
[_keyboardView addObserver:self
forKeyPath:NSStringFromSelector(@selector(frame))
options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew)
context:kJSQMessagesKeyboardControllerKeyValueObservingContext];
_jsq_isObserving = YES;
}
}
@ -110,7 +130,7 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
if (!self.keyboardIsVisible) {
return CGRectNull;
}
return self.keyboardView.frame;
}
@ -121,18 +141,16 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
if (self.textView.inputAccessoryView == nil) {
self.textView.inputAccessoryView = [[UIView alloc] init];
}
[self jsq_registerForNotifications];
}
- (void)endListeningForKeyboard
{
[self jsq_unregisterForNotifications];
[self jsq_setKeyboardViewHidden:NO];
// No need to set keyboardView to nil here
// Plus we need it for future "dismiss keyboard" gesture recognition.
// self.keyboardView = nil;
self.keyboardView = nil;
}
#pragma mark - Notifications
@ -140,22 +158,22 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
- (void)jsq_registerForNotifications
{
[self jsq_unregisterForNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(jsq_didReceiveKeyboardDidShowNotification:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(jsq_didReceiveKeyboardWillChangeFrameNotification:)
name:UIKeyboardWillChangeFrameNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(jsq_didReceiveKeyboardDidChangeFrameNotification:)
name:UIKeyboardDidChangeFrameNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(jsq_didReceiveKeyboardDidHideNotification:)
name:UIKeyboardDidHideNotification
@ -169,24 +187,9 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
- (void)jsq_didReceiveKeyboardDidShowNotification:(NSNotification *)notification
{
UIView *keyboardViewProxy = self.textView.inputAccessoryView.superview;
if ([UIDevice jsq_isCurrentDeviceAfteriOS9]) {
NSPredicate *windowPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", NSClassFromString(@"UIRemoteKeyboardWindow")];
UIWindow *keyboardWindow = [[UIApplication sharedApplication].windows filteredArrayUsingPredicate:windowPredicate].firstObject;
for (UIView *subview in keyboardWindow.subviews) {
for (UIView *hostview in subview.subviews) {
if ([hostview isMemberOfClass:NSClassFromString(@"UIInputSetHostView")]) {
keyboardViewProxy = hostview;
break;
}
}
}
self.keyboardView = keyboardViewProxy;
}
self.keyboardView = self.textView.inputAccessoryView.superview;
[self jsq_setKeyboardViewHidden:NO];
[self jsq_handleKeyboardNotification:notification completion:^(BOOL finished) {
[self.panGestureRecognizer addTarget:self action:@selector(jsq_handlePanGestureRecognizer:)];
}];
@ -200,36 +203,38 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
- (void)jsq_didReceiveKeyboardDidChangeFrameNotification:(NSNotification *)notification
{
[self jsq_setKeyboardViewHidden:NO];
[self jsq_handleKeyboardNotification:notification completion:nil];
}
- (void)jsq_didReceiveKeyboardDidHideNotification:(NSNotification *)notification
{
self.keyboardView = nil;
[self jsq_handleKeyboardNotification:notification completion:^(BOOL finished) {
[self.panGestureRecognizer removeTarget:self action:NULL];
[self.delegate keyboardControllerKeyboardDidHide:self];
}];
}
- (void)jsq_handleKeyboardNotification:(NSNotification *)notification completion:(JSQAnimationCompletionBlock)completion
{
NSDictionary *userInfo = [notification userInfo];
CGRect keyboardEndFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
if (CGRectIsNull(keyboardEndFrame)) {
return;
}
UIViewAnimationCurve animationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
NSInteger animationCurveOption = (animationCurve << 16);
double animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardEndFrameConverted = [self.contextView convertRect:keyboardEndFrame fromView:nil];
[UIView animateWithDuration:animationDuration
delay:0.0
options:animationCurveOption
@ -254,37 +259,31 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
- (void)jsq_notifyKeyboardFrameNotificationForFrame:(CGRect)frame
{
[self.delegate keyboardController:self keyboardDidChangeFrame:frame];
[[NSNotificationCenter defaultCenter] postNotificationName:JSQMessagesKeyboardControllerNotificationKeyboardDidChangeFrame
object:self
userInfo:@{ JSQMessagesKeyboardControllerUserInfoKeyKeyboardDidChangeFrame : [NSValue valueWithCGRect:frame] }];
}
- (void)jsq_resetKeyboardAndTextView
{
[self jsq_setKeyboardViewHidden:YES];
[self jsq_removeKeyboardFrameObserver];
[self.textView resignFirstResponder];
}
#pragma mark - Key-value observing
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == kJSQMessagesKeyboardControllerKeyValueObservingContext) {
if (object == self.keyboardView && [keyPath isEqualToString:NSStringFromSelector(@selector(frame))]) {
CGRect oldKeyboardFrame = [[change objectForKey:NSKeyValueChangeOldKey] CGRectValue];
CGRect newKeyboardFrame = [[change objectForKey:NSKeyValueChangeNewKey] CGRectValue];
if (CGRectEqualToRect(newKeyboardFrame, oldKeyboardFrame) || CGRectIsNull(newKeyboardFrame)) {
return;
}
CGRect keyboardEndFrameConverted = [self.contextView convertRect:newKeyboardFrame
fromView:self.keyboardView.superview];
[self jsq_notifyKeyboardFrameNotificationForFrame:keyboardEndFrameConverted];
// do not convert frame to contextView coordinates here
// KVO is triggered during panning (see below)
// panning occurs in contextView coordinates already
[self jsq_notifyKeyboardFrameNotificationForFrame:newKeyboardFrame];
}
}
}
@ -294,14 +293,14 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
if (!_jsq_isObserving) {
return;
}
@try {
[_keyboardView removeObserver:self
forKeyPath:NSStringFromSelector(@selector(frame))
context:kJSQMessagesKeyboardControllerKeyValueObservingContext];
}
@catch (NSException * __unused exception) { }
_jsq_isObserving = NO;
}
@ -309,42 +308,42 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
- (void)jsq_handlePanGestureRecognizer:(UIPanGestureRecognizer *)pan
{
CGPoint touch = [pan locationInView:self.contextView.window];
CGPoint touch = [pan locationInView:self.contextView];
// system keyboard is added to a new UIWindow, need to operate in window coordinates
// also, keyboard always slides from bottom of screen, not the bottom of a view
CGFloat contextViewWindowHeight = CGRectGetHeight(self.contextView.window.frame);
if ([UIDevice jsq_isCurrentDeviceBeforeiOS8]) {
// handle iOS 7 bug when rotating to landscape
if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
contextViewWindowHeight = CGRectGetWidth(self.contextView.window.frame);
}
}
CGFloat keyboardViewHeight = CGRectGetHeight(self.keyboardView.frame);
CGFloat dragThresholdY = (contextViewWindowHeight - keyboardViewHeight - self.keyboardTriggerPoint.y);
CGRect newKeyboardViewFrame = self.keyboardView.frame;
BOOL userIsDraggingNearThresholdForDismissing = (touch.y > dragThresholdY);
self.keyboardView.userInteractionEnabled = !userIsDraggingNearThresholdForDismissing;
switch (pan.state) {
case UIGestureRecognizerStateChanged:
{
newKeyboardViewFrame.origin.y = touch.y + self.keyboardTriggerPoint.y;
// bound frame between bottom of view and height of keyboard
newKeyboardViewFrame.origin.y = MIN(newKeyboardViewFrame.origin.y, contextViewWindowHeight);
newKeyboardViewFrame.origin.y = MAX(newKeyboardViewFrame.origin.y, contextViewWindowHeight - keyboardViewHeight);
if (CGRectGetMinY(newKeyboardViewFrame) == CGRectGetMinY(self.keyboardView.frame)) {
return;
}
[UIView animateWithDuration:0.0
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionTransitionNone
@ -354,23 +353,22 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
completion:nil];
}
break;
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateFailed:
{
BOOL keyboardViewIsHidden = (CGRectGetMinY(self.keyboardView.frame) >= contextViewWindowHeight);
if (keyboardViewIsHidden) {
[self jsq_resetKeyboardAndTextView];
return;
}
CGPoint velocity = [pan velocityInView:self.contextView];
BOOL userIsScrollingDown = (velocity.y > 0.0f);
BOOL shouldHide = (userIsScrollingDown && userIsDraggingNearThresholdForDismissing);
newKeyboardViewFrame.origin.y = shouldHide ? contextViewWindowHeight : (contextViewWindowHeight - keyboardViewHeight);
[UIView animateWithDuration:0.25
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationCurveEaseOut
@ -379,9 +377,11 @@ typedef void (^JSQAnimationCompletionBlock)(BOOL finished);
}
completion:^(BOOL finished) {
self.keyboardView.userInteractionEnabled = !shouldHide;
if (shouldHide) {
[self jsq_resetKeyboardAndTextView];
[self jsq_setKeyboardViewHidden:YES];
[self jsq_removeKeyboardFrameObserver];
[self.textView resignFirstResponder];
}
}];
}

View File

@ -21,7 +21,6 @@
#import "JSQMessagesCollectionView.h"
#import "JSQMessagesCollectionViewFlowLayout.h"
#import "JSQMessagesInputToolbar.h"
#import "JSQMessagesKeyboardController.h"
/**
* The `JSQMessagesViewController` class is an abstract class that represents a view controller whose content consists of
@ -34,43 +33,40 @@
UITextViewDelegate>
/**
* Returns the collection view object managed by this view controller.
* Returns the collection view object managed by this view controller.
* This view controller is the collection view's data source and delegate.
*/
@property (weak, nonatomic, readonly) JSQMessagesCollectionView *collectionView;
/**
* Returns the input toolbar view object managed by this view controller.
* Returns the input toolbar view object managed by this view controller.
* This view controller is the toolbar's delegate.
*/
@property (weak, nonatomic, readonly) JSQMessagesInputToolbar *inputToolbar;
/**
* Returns the keyboard controller object used to manage the software keyboard.
*/
@property (strong, nonatomic) JSQMessagesKeyboardController *keyboardController;
/**
* The display name of the current user who is sending messages.
* This value does not have to be unique.
*
* @discussion This value does not have to be unique. This value must not be `nil`.
* @discussion This value must not be `nil`. The default value is `@"JSQDefaultSender"`.
*/
@property (copy, nonatomic) NSString *senderDisplayName;
/**
* The string identifier that uniquely identifies the current user sending messages.
*
*
* @discussion This property is used to determine if a message is incoming or outgoing.
* All message data objects returned by `collectionView:messageDataForItemAtIndexPath:` are
* checked against this identifier. This value must not be `nil`.
* checked against this identifier.
* This value must not be `nil`. The default value is `@"JSQDefaultSender"`.
*/
@property (copy, nonatomic) NSString *senderId;
/**
* Specifies whether or not the view controller should automatically scroll to the most recent message
* Specifies whether or not the view controller should automatically scroll to the most recent message
* when the view appears and when sending, receiving, and composing a new message.
*
* @discussion The default value is `YES`, which allows the view controller to scroll automatically to the most recent message.
* @discussion The default value is `YES`, which allows the view controller to scroll automatically to the most recent message.
* Set to `NO` if you want to manage scrolling yourself.
*/
@property (assign, nonatomic) BOOL automaticallyScrollsToMostRecentMessage;
@ -82,7 +78,7 @@
* @discussion This cell identifier is used for outgoing text message data items.
* The default value is the string returned by `[JSQMessagesCollectionViewCellOutgoing cellReuseIdentifier]`.
* This value must not be `nil`.
*
*
* @see JSQMessagesCollectionViewCellOutgoing.
*
* @warning Overriding this property's default value is *not* recommended.
@ -94,7 +90,7 @@
@property (copy, nonatomic) NSString *outgoingCellIdentifier;
/**
* The collection view cell identifier to use for dequeuing outgoing message collection view cells
* The collection view cell identifier to use for dequeuing outgoing message collection view cells
* in the collectionView for media messages.
*
* @discussion This cell identifier is used for outgoing media message data items.
@ -147,6 +143,28 @@
*/
@property (copy, nonatomic) NSString *incomingMediaCellIdentifier;
/*
* The collection view cell identifier used to dequeue call collection view cell.
*
* @discussion This cell identifier's default value is returned by [JSQCallCollectionViewCell cellReuseIdentifier]. Value must not be nil.
*
* @see JSQCallCollectionViewCell
*
*/
@property (copy, nonatomic) NSString *callCellIndentifier;
/*
* The collection view cell identifier used to dequeue displayed message collection view cell.
*
* @discussion This cell identifier's default value is returned by [JSQDisplayedMessageCollectionViewCell cellReuseIdentifier]. Value must not be nil.
*
* @see JSQDisplayedMessageCollectionViewCell
*
*/
@property (copy, nonatomic) NSString *displayedMessageCellIndentifier;
/**
* Specifies whether or not the view controller should show the typing indicator for an incoming message.
*
@ -177,7 +195,7 @@
/**
* Returns the `UINib` object initialized for a `JSQMessagesViewController`.
*
* @return The initialized `UINib` object or `nil` if there were errors during initialization
* @return The initialized `UINib` object or `nil` if there were errors during initialization
* or the nib file could not be located.
*
* @discussion You may override this method to provide a customized nib. If you do,
@ -188,7 +206,7 @@
/**
* Creates and returns a new `JSQMessagesViewController` object.
*
*
* @discussion This is the designated initializer for programmatic instantiation.
*
* @return An initialized `JSQMessagesViewController` object if successful, `nil` otherwise.
@ -268,60 +286,4 @@
*/
- (void)scrollToBottomAnimated:(BOOL)animated;
/**
* Used to decide if a message is incoming or outgoing.
*
* @discussion The default implementation of this method compares the `senderId` of the message to the
* value of the `senderId` property and returns `YES` if they are equal. Subclasses can override
* this method to specialize the decision logic.
*/
- (BOOL)isOutgoingMessage:(id<JSQMessageData>)messageItem;
/**
* Scrolls the collection view so that the cell at the specified indexPath is completely visible above the `inputToolbar`.
*
* @param indexPath The indexPath for the cell that will be visible.
* @param animated Pass `YES` if you want to animate scrolling, `NO` otherwise.
*/
- (void)scrollToIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;
/**
Call to super required.
*/
- (void)viewDidLoad NS_REQUIRES_SUPER;
/**
Call to super required.
*/
- (void)viewWillAppear:(BOOL)animated NS_REQUIRES_SUPER;
/**
Call to super required.
*/
- (void)viewDidAppear:(BOOL)animated NS_REQUIRES_SUPER;
/**
Call to super required.
*/
- (void)viewWillDisappear:(BOOL)animated NS_REQUIRES_SUPER;
/**
Call to super required.
*/
- (void)viewDidDisappear:(BOOL)animated NS_REQUIRES_SUPER;
/**
Called when `UIMenuControllerWillShowMenuNotification` is posted.
@param notification The posted notification.
*/
- (void)didReceiveMenuWillShowNotification:(NSNotification *)notification;
/**
Called when `UIMenuControllerWillHideMenuNotification` is posted.
@param notification The posted notification.
*/
- (void)didReceiveMenuWillHideNotification:(NSNotification *)notification;
@end

View File

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6245" systemVersion="13F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6238"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="JSQMessagesViewController">
@ -46,4 +45,9 @@
<nil key="simulatedStatusBarMetrics"/>
</view>
</objects>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View File

@ -21,6 +21,22 @@
#import "UIColor+JSQMessages.h"
@interface JSQMessagesAvatarImageFactory ()
+ (UIImage *)jsq_circularImage:(UIImage *)image
withDiamter:(NSUInteger)diameter
highlightedColor:(UIColor *)highlightedColor;
+ (UIImage *)jsq_imageWitInitials:(NSString *)initials
backgroundColor:(UIColor *)backgroundColor
textColor:(UIColor *)textColor
font:(UIFont *)font
diameter:(NSUInteger)diameter;
@end
@implementation JSQMessagesAvatarImageFactory
#pragma mark - Public
@ -28,9 +44,9 @@
+ (JSQMessagesAvatarImage *)avatarImageWithPlaceholder:(UIImage *)placeholderImage diameter:(NSUInteger)diameter
{
UIImage *circlePlaceholderImage = [JSQMessagesAvatarImageFactory jsq_circularImage:placeholderImage
withDiameter:diameter
withDiamter:diameter
highlightedColor:nil];
return [JSQMessagesAvatarImage avatarImageWithPlaceholder:circlePlaceholderImage];
}
@ -38,7 +54,7 @@
{
UIImage *avatar = [JSQMessagesAvatarImageFactory circularAvatarImage:image withDiameter:diameter];
UIImage *highlightedAvatar = [JSQMessagesAvatarImageFactory circularAvatarHighlightedImage:image withDiameter:diameter];
return [[JSQMessagesAvatarImage alloc] initWithAvatarImage:avatar
highlightedImage:highlightedAvatar
placeholderImage:avatar];
@ -47,14 +63,14 @@
+ (UIImage *)circularAvatarImage:(UIImage *)image withDiameter:(NSUInteger)diameter
{
return [JSQMessagesAvatarImageFactory jsq_circularImage:image
withDiameter:diameter
withDiamter:diameter
highlightedColor:nil];
}
+ (UIImage *)circularAvatarHighlightedImage:(UIImage *)image withDiameter:(NSUInteger)diameter
{
return [JSQMessagesAvatarImageFactory jsq_circularImage:image
withDiameter:diameter
withDiamter:diameter
highlightedColor:[UIColor colorWithWhite:0.1f alpha:0.3f]];
}
@ -69,11 +85,11 @@
textColor:textColor
font:font
diameter:diameter];
UIImage *avatarHighlightedImage = [JSQMessagesAvatarImageFactory jsq_circularImage:avatarImage
withDiameter:diameter
withDiamter:diameter
highlightedColor:[UIColor colorWithWhite:0.1f alpha:0.3f]];
return [[JSQMessagesAvatarImage alloc] initWithAvatarImage:avatarImage
highlightedImage:avatarHighlightedImage
placeholderImage:avatarImage];
@ -92,64 +108,70 @@
NSParameterAssert(textColor != nil);
NSParameterAssert(font != nil);
NSParameterAssert(diameter > 0);
CGRect frame = CGRectMake(0.0f, 0.0f, diameter, diameter);
NSString *text = [initials uppercaseStringWithLocale:[NSLocale currentLocale]];
NSDictionary *attributes = @{ NSFontAttributeName : font,
NSForegroundColorAttributeName : textColor };
CGRect textFrame = [initials boundingRectWithSize:frame.size
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:attributes
context:nil];
CGRect textFrame = [text boundingRectWithSize:frame.size
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:attributes
context:nil];
CGPoint frameMidPoint = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame));
CGPoint textFrameMidPoint = CGPointMake(CGRectGetMidX(textFrame), CGRectGetMidY(textFrame));
CGFloat dx = frameMidPoint.x - textFrameMidPoint.x;
CGFloat dy = frameMidPoint.y - textFrameMidPoint.y;
CGPoint drawPoint = CGPointMake(dx, dy);
UIImage *image = nil;
UIGraphicsBeginImageContextWithOptions(frame.size, NO, [UIScreen mainScreen].scale);
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
CGContextFillRect(context, frame);
[initials drawAtPoint:drawPoint withAttributes:attributes];
[text drawAtPoint:drawPoint withAttributes:attributes];
image = UIGraphicsGetImageFromCurrentImageContext();
CGContextRestoreGState(context);
}
UIGraphicsEndImageContext();
return [JSQMessagesAvatarImageFactory jsq_circularImage:image withDiameter:diameter highlightedColor:nil];
return [JSQMessagesAvatarImageFactory jsq_circularImage:image withDiamter:diameter highlightedColor:nil];
}
+ (UIImage *)jsq_circularImage:(UIImage *)image withDiameter:(NSUInteger)diameter highlightedColor:(UIColor *)highlightedColor
+ (UIImage *)jsq_circularImage:(UIImage *)image withDiamter:(NSUInteger)diameter highlightedColor:(UIColor *)highlightedColor
{
NSParameterAssert(image != nil);
NSParameterAssert(diameter > 0);
CGRect frame = CGRectMake(0.0f, 0.0f, diameter, diameter);
UIImage *newImage = nil;
UIGraphicsBeginImageContextWithOptions(frame.size, NO, [UIScreen mainScreen].scale);
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
UIBezierPath *imgPath = [UIBezierPath bezierPathWithOvalInRect:frame];
[imgPath addClip];
[image drawInRect:frame];
if (highlightedColor != nil) {
CGContextSetFillColorWithColor(context, highlightedColor.CGColor);
CGContextFillEllipseInRect(context, frame);
}
newImage = UIGraphicsGetImageFromCurrentImageContext();
CGContextRestoreGState(context);
}
UIGraphicsEndImageContext();

View File

@ -73,4 +73,7 @@
*/
- (JSQMessagesBubbleImage *)incomingMessagesBubbleImageWithColor:(UIColor *)color;
- (JSQMessagesBubbleImage *)outgoingMessageFailedBubbleImageWithColor:(UIColor *)color;
@end

View File

@ -27,6 +27,14 @@
@property (strong, nonatomic, readonly) UIImage *bubbleImage;
@property (assign, nonatomic, readonly) UIEdgeInsets capInsets;
- (UIEdgeInsets)jsq_centerPointEdgeInsetsForImageSize:(CGSize)bubbleImageSize;
- (JSQMessagesBubbleImage *)jsq_messagesBubbleImageWithColor:(UIColor *)color flippedForIncoming:(BOOL)flippedForIncoming;
- (UIImage *)jsq_horizontallyFlippedImageFromImage:(UIImage *)image;
- (UIImage *)jsq_stretchableImageFromImage:(UIImage *)image withCapInsets:(UIEdgeInsets)capInsets;
@end
@ -58,6 +66,11 @@
return [self initWithBubbleImage:[UIImage jsq_bubbleCompactImage] capInsets:UIEdgeInsetsZero];
}
- (void)dealloc
{
_bubbleImage = nil;
}
#pragma mark - Public
- (JSQMessagesBubbleImage *)outgoingMessagesBubbleImageWithColor:(UIColor *)color
@ -70,6 +83,11 @@
return [self jsq_messagesBubbleImageWithColor:color flippedForIncoming:YES];
}
- (JSQMessagesBubbleImage *)outgoingMessageFailedBubbleImageWithColor:(UIColor *)color
{
return [self jsq_messagesBubbleImageWithColor:color flippedForIncoming:NO];
}
#pragma mark - Private
- (UIEdgeInsets)jsq_centerPointEdgeInsetsForImageSize:(CGSize)bubbleImageSize

View File

@ -61,7 +61,7 @@
* @see JSQMessagesBubbleImageFactory.
* @see JSQMessagesBubbleImage.
*/
- (instancetype)initWithBubbleImageFactory:(JSQMessagesBubbleImageFactory *)bubbleImageFactory NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithBubbleImageFactory:(JSQMessagesBubbleImageFactory *)bubbleImageFactory;
/**
* Applies an outgoing bubble image mask to the specified mediaView.

View File

@ -21,6 +21,13 @@
#import "JSQMessagesBubbleImageFactory.h"
@interface JSQMessagesMediaViewBubbleImageMasker ()
- (void)jsq_maskView:(UIView *)view withImage:(UIImage *)image;
@end
@implementation JSQMessagesMediaViewBubbleImageMasker
#pragma mark - Initialization

View File

@ -66,6 +66,13 @@
return self;
}
- (void)dealloc
{
_dateFormatter = nil;
_dateTextAttributes = nil;
_timeTextAttributes = nil;
}
#pragma mark - Formatter
- (NSString *)timestampForDate:(NSDate *)date

View File

@ -20,7 +20,6 @@
#import "UIColor+JSQMessages.h"
#import "UIImage+JSQMessages.h"
#import "NSBundle+JSQMessages.h"
@implementation JSQMessagesToolbarButtonFactory
@ -28,51 +27,49 @@
+ (UIButton *)defaultAccessoryButtonItem
{
UIImage *accessoryImage = [UIImage jsq_defaultAccessoryImage];
UIImage *normalImage = [accessoryImage jsq_imageMaskedWithColor:[UIColor lightGrayColor]];
UIImage *normalImage = [accessoryImage jsq_imageMaskedWithColor:[UIColor colorWithRed:0 green:71/255.f blue:1.0f alpha:1.0f]];
UIImage *highlightedImage = [accessoryImage jsq_imageMaskedWithColor:[UIColor darkGrayColor]];
UIButton *accessoryButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, accessoryImage.size.width, 32.0f)];
[accessoryButton setImage:normalImage forState:UIControlStateNormal];
[accessoryButton setImage:highlightedImage forState:UIControlStateHighlighted];
accessoryButton.contentMode = UIViewContentModeScaleAspectFit;
accessoryButton.backgroundColor = [UIColor clearColor];
accessoryButton.tintColor = [UIColor lightGrayColor];
//accessoryButton.tintColor = [UIColor lightGrayColor];
accessoryButton.accessibilityLabel = [NSBundle jsq_localizedStringForKey:@"accessory_button_accessibility_label"];
return accessoryButton;
}
+ (UIButton *)defaultSendButtonItem
{
NSString *sendTitle = [NSBundle jsq_localizedStringForKey:@"send"];
NSString *sendTitle = NSLocalizedStringFromTable(@"Send", @"JSQMessages", @"Text for the send button on the messages view toolbar");
UIButton *sendButton = [[UIButton alloc] initWithFrame:CGRectZero];
[sendButton setTitle:sendTitle forState:UIControlStateNormal];
[sendButton setTitleColor:[UIColor jsq_messageBubbleBlueColor] forState:UIControlStateNormal];
[sendButton setTitleColor:[[UIColor jsq_messageBubbleBlueColor] jsq_colorByDarkeningColorWithValue:0.1f] forState:UIControlStateHighlighted];
[sendButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled];
sendButton.titleLabel.font = [UIFont boldSystemFontOfSize:17.0f];
sendButton.titleLabel.font = [UIFont fontWithName:@"HelveticaNeue-Thin" size:17.0f];
sendButton.titleLabel.adjustsFontSizeToFitWidth = YES;
sendButton.titleLabel.minimumScaleFactor = 0.85f;
sendButton.contentMode = UIViewContentModeCenter;
sendButton.backgroundColor = [UIColor clearColor];
sendButton.tintColor = [UIColor jsq_messageBubbleBlueColor];
CGFloat maxHeight = 32.0f;
CGRect sendTitleRect = [sendTitle boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, maxHeight)
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:@{ NSFontAttributeName : sendButton.titleLabel.font }
context:nil];
sendButton.frame = CGRectMake(0.0f,
0.0f,
CGRectGetWidth(CGRectIntegral(sendTitleRect)),
maxHeight);
return sendButton;
}

View File

@ -29,12 +29,9 @@
#import "JSQMessagesLoadEarlierHeaderView.h"
// Layout
#import "JSQMessagesBubbleSizeCalculating.h"
#import "JSQMessagesBubblesSizeCalculator.h"
#import "JSQMessagesCollectionViewFlowLayout.h"
#import "JSQMessagesCollectionViewLayoutAttributes.h"
#import "JSQMessagesCollectionViewFlowLayoutInvalidationContext.h"
#import "JSQAudioMediaViewAttributes.h"
// Toolbar
#import "JSQMessagesComposerTextView.h"
@ -45,7 +42,6 @@
#import "JSQMessage.h"
#import "JSQMediaItem.h"
#import "JSQAudioMediaItem.h"
#import "JSQPhotoMediaItem.h"
#import "JSQLocationMediaItem.h"
#import "JSQVideoMediaItem.h"
@ -53,8 +49,6 @@
#import "JSQMessagesBubbleImage.h"
#import "JSQMessagesAvatarImage.h"
#import "JSQAudioMediaViewAttributes.h"
// Protocols
#import "JSQMessageData.h"
#import "JSQMessageMediaData.h"
@ -76,6 +70,5 @@
#import "UIColor+JSQMessages.h"
#import "UIImage+JSQMessages.h"
#import "UIView+JSQMessages.h"
#import "NSBundle+JSQMessages.h"
#endif

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