jessesquires / JSQMessagesViewController

An elegant messages UI library for iOS
https://www.jessesquires.com/blog/officially-deprecating-jsqmessagesviewcontroller/
Other
11.14k stars 2.82k forks source link

VERSION 5.0 #172

Closed jessesquires closed 10 years ago

jessesquires commented 10 years ago

With v4.0.0 kicked off as the last stable release for iOS 6, it's now time to begin v5.0.0.

I have better-organized the issues here on GitHub, and plan to keep everyone informed of the plans for v5.0.0 in this thread. If you have any questions, comments, or suggestions, please leave them below.

All work on version 5.0.0 will happen on branch version_5_release exclusively. Please feel free to checkout this branch periodically to see my progress or even submit bug fixes!

Version 5.0.0

iOS support changes

Refactoring / Structural changes

New features

Maintenance

Documentation

Unit Tests

Nice to have / Future work

As noted above, I will no longer be supporting iOS 6. (And you shouldn't either! As of this writing, iOS 7 adoption rates are estimated at 80%.) Please note, because of the changes listed above, v4.0 and v5.0 will be entirely incompatible.

However, some may wish to continue supporting iOS 6. For this reason, I've created the branch iOS6_support_stable. I will not be contributing to this branch myself, but I will continue to accept pull requests.

robj commented 10 years ago

Great to see the road-plan moving forward!.One note regarding Pagination/Infinite Scrolling. I found it could be implemented fairly simply using this top-infinitescrolling branch of SVPullToRefresh - https://github.com/Gabro/SVPullToRefresh/tree/top-infinitescrolling

jessesquires commented 10 years ago

@robj -- nice! :+1:

bassrock commented 10 years ago

:+1: Good to see this going! Great job!

vr-devil commented 10 years ago

good!

iainsmith commented 10 years ago

Sounds great.

jessesquires commented 10 years ago

For those eager to see the current progress:

  1. checkout branch version_5_release
  2. run pod update
  3. build and run the demo (open the workspace, not project)

Basic collectionViewCell prototypes, layout, and toolbar are done. What you'll see in the demo is just some static placeholders, no real content or functionality yet. But, you should be able to get the idea and see where it's going. :)

Works on any device, any orientation. Performance is awesome. :+1:

Next steps are completing functionality and building out the public APIs.

jessesquires commented 10 years ago

Hello all!

I'm getting very close to a release-ready version!

Because these changes have been so drastic and improve the control so much (basically closing all existing bugs so far), I think I'm going to try to release v5.0 sooner rather than later -- that is, release 5.0 without the much anticipated image/media messages feature.

Then, I'd like to quickly iterate to add image/media messages in v5.1. The goal here would be to create the framework in such a way that adding image/media messages will be almost trivial and would not require much (if any) refactoring and would leave the API established in v5.0 intact. (So far, I think this is the case!)

This way, everyone can switch over to the latest version (5.0) and get comfortable with it. And maybe even help squash some initial bugs.

Warning! There will be absolutely no backwards compatibility from v4.0 to v5.0. However, it will be worth it.

I encourage you all to checkout the progress so far on branch version_5_release. I would pull this down to a clean directory that you can throw away later.

robj commented 10 years ago

Great Jesse, Looking forward to testing it out.

In preparation for 5.1 I added a summary of my experiences with current forks that have media message support to https://github.com/jessesquires/MessagesTableViewController/pull/97

jessesquires commented 10 years ago

@robj - thanks for getting that info together!

also, i should note, in the current demo (v5.0), the send button is not implemented yet. but, basically all layout work is done.

cswelin commented 10 years ago

Just a quick question, been toying around with every new commit. Is the intention for the bubble background to expand the width of the cell? or wrap to the size of the content? currently its the former of the two.

jessesquires commented 10 years ago

@cswelin -- ah, yes. bubble widths should be variable. the current build is calculating the right sizes (w, h) - but only setting the height for now.

there are a few different strategies for setting the width and i'm trying to decide which is optimal. the reason this isn't a cut-and-paste of previous code is because this using autoLayout and collectionView.

good question!

koenbud commented 10 years ago

Hi @jessesquires, thanks for this awesome control. I have been playing around with the version 5 branch and I would like to hide the sender name. Should I use configureItemAtIndexPath delegate method for that? Can you give me a quick example of how I would use that?

jessesquires commented 10 years ago

@koenbud - thanks! this is another thing that is in-progress right now. it's actually going to get refactored and the APIs are going to change - but it will be an easy thing to do. i'll keep you posted!

robj commented 10 years ago

Here is a Podspec for anyone wishing to test this branch using cocoapods.

https://github.com/robj/MessagesTableViewController/blob/patch-1/JSQMessagesViewController.podspec

koenbud commented 10 years ago

@jessesquires, in my app the messages view is never scrolled down all the way when it appears. Is there something wrong in my app or is this known behaviour?

Screenshot: http://i.imgur.com/oY4qNwR.png

jessesquires commented 10 years ago

hey @koenbud -- yes, this is a known issue when pushing from a nav controller. however, this does not happen when presenting modally. the issue is with the content size and scroll offset during load -- still not sure why this is happening. (feel free to investigate further!)

i've updated the demo recently, pull the latest and check it out!

koenbud commented 10 years ago

Alright thanks, I'll take a look :)

alexito4 commented 10 years ago

Hi! About the scrollToBottom issue I find that it seems like in the viewWillAppear the layout isn't correct yet. The frame and the insets of the collectionView are right but it seems that the internal layout is not calculated yet. If you move [self scrollToBottomAnimated:NO]; from the viewWillAppear to viewDidAppear it works fine. But, of course, we want that to be in the viewWillAppear so I tried to call at the next runloop and it works. (with dispatch_async or with dispatch_after):

if (self.autoScrollsToMostRecentMessage) {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self scrollToBottomAnimated:NO];
        [self.collectionView.collectionViewLayout invalidateLayout];
    });
}

EDIT: it seems a problem with autolayout: http://stackoverflow.com/questions/19121607/contentoffset-not-updated-on-uicollectionview-if-scrolltoitematindexpath-is-call

And another thing; I find it strange that when I create the controller from the nib (with initWithNibName:bundle:) it calls viewDidLoad: right away. I normally expect that the viewDidLoad call is not made until I push/present the view controller. I see that the call to [self jsq_configureViewController]; happens when de nib is loaded, is any plan to change that or it's fine?

;)

marcphk commented 10 years ago

Jesse - is there any way you could include support for the iMessage writing message indicator bubbles that are in iOS 6 and iOS 7?

jessesquires commented 10 years ago

@alexito4: thanks for looking into the scrolling issue! i've just pushed the fix.

regarding the view loading: though this might be somewhat atypical, i wouldn't worry about it. the initialization flow is currently constructed how it needs to be in order to provide the necessary hooks for subclasses to override defaults, while providing fully/properly initialized objects at the time of override -- regardless of whether you load from storyboards or programmatically. i really wanted to give devs a choice for how to initialize and present this view controller. further, it is not common to initialize a view controller and not present it either immediately or very soon after initialization, so the precise time of loading the view should not matter or impact performance. however, it you do see any performance issues then i would recommend loading from storyboards (which will be the recommended way to init when 5.0 is out).

EDIT: @alexito4 : i found some other issues with the initialization flow. just pushed fixes and the flow is now as you would expect, no anomalies (i.e., viewDidLoad is not called until presentation)

@magicmarc: i'm planning on adding that! :)

Gilmargolin commented 10 years ago

is there any example on how to implement the writing message indicator?

cswelin commented 10 years ago

There's still a slight scrolling issue, if you changed the demo app to only show only these messages

  self.messages = [[NSMutableArray alloc] initWithObjects:
                     [[JSQMessage alloc] initWithText:@"Welcome to JSQMessages. Simple, elegant, easy to use." sender:kJSQDemoAvatarNameJesse date:[NSDate distantPast]],
                     [[JSQMessage alloc] initWithText:@"There are super sweet default settings, but you can customize this like crazy." sender:kJSQDemoAvatarNameWoz date:[NSDate distantPast]],
                     [[JSQMessage alloc] initWithText:@"It even has data detectors. You can call me tonight. My cell number is 123-456-7890. \nMy website is www.hexedbits.com." sender:kJSQDemoAvatarNameJesse date:[NSDate distantPast]],
                     [[JSQMessage alloc] initWithText:@"JSQMessagesViewController is nearly an exact replica of the iOS Messages App." sender:kJSQDemoAvatarNameJobs date:[NSDate distantPast]],

                     nil];

and comment out

NSUInteger messagesToAdd = 1;
    for (NSUInteger i = 0; i < messagesToAdd; i++) {
        [self.messages addObjectsFromArray:self.messages];
    }

the last messages is covered, this goes for storyboards and Modal.

jessesquires commented 10 years ago

@cswelin - wow. what an edge case! as @alexito4 noted, this seems to be a bug with auto-layout.

Luckily, I've narrowed it down to the following condition: When the contentSize.height is just slightly smaller (~ 472) or slightly larger (~ 592) than the bounds.size.height (568), scrolling fails. Otherwise, it's ok.

Unfortunately, I think this is something we'll just have to live with for now. :(

jessesquires commented 10 years ago

Update: Hello all, major changes just pushed. Bubble sizes now accurately computed. API is starting to solidify (and might be final!). What's left? some finishing touches + docs and tests. :)

cswelin commented 10 years ago

Testing the latest changes, when disabling the avatars (returning nil) the view is draw correctly on load, however, when you scroll or rotate everything gets shifted over as if the avatars were suppose to be there.

Also, doing a full 360 rotate throws

Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x94a5620 H:[UIView:0x94a5590(34)]>",
    "<NSLayoutConstraint:0x94a5ce0 H:[UIView:0x94a5590]-(2)-[UIView:0x949ed20]>",
    "<NSLayoutConstraint:0x94a5d70 JSQMessagesCollectionViewCellIncoming:0x949e0c0.trailing == UIView:0x949ed20.trailing + 285>",
    "<NSLayoutConstraint:0x94a5da0 UIView:0x94a5590.leading == JSQMessagesCollectionViewCellIncoming:0x949e0c0.leading>",
    "<NSLayoutConstraint:0x94a4820 'UIView-Encapsulated-Layout-Width' H:[JSQMessagesCollectionViewCellIncoming:0x949e0c0(312)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x94a5620 H:[UIView:0x94a5590(34)]>
jessesquires commented 10 years ago

@cswelin - you also need to tell the layout the avatar size :)

self.collectionView.collectionViewLayout.avatarViewSize = CGSizeZero;

(similar to collectionViewLayout.itemSize)

cswelin commented 10 years ago

haha, feel dumb now.

Thanks.

Antairez commented 10 years ago

Absolutely fantastic project, just donated. I am playing with the ios7 branch now, and I realized tap to copy and the - (NSAttributedString )collectionView:(JSQMessagesCollectionView )collectionView sender:(NSString )sender attributedTextForCellBottomLabelAtIndexPath:(NSIndexPath )indexPath {} seems to be not working. Are these 2 functions still under development? Great work Jesse! Thanks for the project.

jessesquires commented 10 years ago

thanks @Antairez !

  1. tap to copy not yet implemented
  2. for the labels, be sure to implement the corresponding delegate method ...heightForCellBottomLabelAtIndexPath:
jessesquires commented 10 years ago

@cswelin -- just FYI, pushed changes tonight that allow you to specify incoming and outgoing avatar sizes.

self.collectionView.collectionViewLayout.incomingAvatarViewSize = // size
self.collectionView.collectionViewLayout.outgoingAvatarViewSize = // size
koenbud commented 10 years ago

@jessesquires -- I just updated to your latest version 5 commit (from 15 days old https://github.com/jessesquires/MessagesTableViewController/commit/252eb6c19da3a7b4089f43cac706f2646f71fdd0). I am kind of stuck now. I've browsed through the demo a couple of times but couldn't find out how to set the delegates.

Earlier I was able to use this code from the demo in https://github.com/jessesquires/MessagesTableViewController/commit/252eb6c19da3a7b4089f43cac706f2646f71fdd0:

self.delegate = self;
JSQMessagesCollectionViewFlowLayout *collectionViewLayout = (JSQMessagesCollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
    collectionViewLayout.delegate = self;

Edit: Some clarifications.

jessesquires commented 10 years ago

@koenbud - ah yes. sorry for any confusion. the delegate/datasource have been refactored and simplified.

the pattern now:

  1. there is one dataSource on the collectionView that extends UICollectionViewDataSource
  2. there is one delegate on the collectionView that extends UICollectionViewDelegateFlowLayout

JSQMessagesViewController now sets itself to each of these, similar to the functionality of UICollectionViewController. All you need to do is override the delegate methods that you need/want.

The methods that previously existed for self.delegate are simply methods on the viewController that you need to override.

The demo has been updated for all of these changes.

koenbud commented 10 years ago

@jessesquires - My co-founder (Val) just sent you a donation (15 mins ago). Keep up the great work you are doing.

jessesquires commented 10 years ago

thanks @koenbud ! :) :)

garrettmurray commented 10 years ago

I was playing with the 5.0 branch today trying to see if I could implement it in a project I'm working on but it's very unclear how that should be done. You mentioned the docs and demo were updated but it doesn't look like the docs are accurate. When do you think you might update those so it's clear how this should be implemented now? Looking forward to using this, some awesome work in here.

jessesquires commented 10 years ago

hey @garrettmurray ! thanks! :)

the demo on this branch is up-to-date, and i'm still working on docs. also, there are still some features that aren't finished (but those are mostly minor). the current cocoa docs link references v4.0 and those won't be updated/re-genrated until v5.0 is out.

for now, you can check the header files on the version_5_release branch for documentation, but not everything has docs written yet. also, i've tried to comment the demo project pretty well. let me know if you need more help!

hactar commented 10 years ago

Just a quick note on the "Image messages, modular enough so consumers can load asynchronously if desired". When working on the generalisation on image/media messages, it would be great if you could consider taking that a step further so that developers can provide any type of UIView to be displayed. That would allow developers to include map views, or custom made views, and of course image views and what not.

Appreciate the work you're doing.

jessesquires commented 10 years ago

@hactar - excellent idea!

jessesquires commented 10 years ago

new issue for planning / discussion regarding media messages: #223

wdcurry commented 10 years ago

Jesse.. absolutely appreciate all this effort! v5 is looking awesome. One thing that reverbs at my end is that a huge percentage of chats are between 2 people. This is the massively main use-case. To that end, i will be implementing an augmentation at my end that sets the entire control to this main use-case, and removes all the avatars, repeated names etc within the chat window. (think of WhatsApp and how clean its' chat window is) .. i will move the other user's avatar to the titlebar and place their name there as well. This will clean things up.

I am recording this, not as a criticism, but as a seed in case you agree.

As well, i will look into a new placement for the camera icon as it takes up too much real-estate for the #1 actionable item (typing text)..

jessesquires commented 10 years ago

@wdcurry - thanks! i agree. all of this is completely and easily customizable. by setting the right properties and using the delegate/datasource appropriately, you can achieve this with very little effort. the current demo is setup how it is for testing purposes.

i will be updating the demo with more examples soon.

mmarkov-appolica commented 10 years ago

The project is one of the best i've seen. I'm not sure if the right place is here for reporting a bug, but i'll post it here. If i use the controller as child the keyboard is over the input field and the layout is broken.

jessesquires commented 10 years ago

@mmarkov-appolica - please open a new issue for this.

mrojas commented 10 years ago

Hello Jesse, First of all, great project! I'm using the version_5_release branch and I know it's under development, but I wanted to let you know about a crash I'm seeing. How to reproduce:

[self.collectionView insertItemsAtIndexPaths:@[[NSIndexPath indexPathForRow:self.messages.count-1 inSection:0]]];

jessesquires commented 10 years ago

@mrojas - it looks like you are adding cells without updating your datasource.

you should call [self finishSending]; at the end of the send method. there's no need to manually insert items into the collectionView. JSQMessagesVC handles this for you.

mrojas commented 10 years ago

Hi Jesse, I see. But I'm not calling this from the send method, I was talking about a received message (In fact the sending of messages worked fine). My app stays connected to a socket and can receive messages at any time. I have removed the lines where items are inserted manually and I'm using finishSending (even when it's not actually sending a message). That works, but the following line in finishSending clears the text if on the receiving side I'm typing something and during that time I receive a new message:

textView.text = nil;

I suggest having two methods: finishSending and didReceiveMessage. They both would be very similar except for the following two lines which should not be included in didReceiveMessage

textView.text = nil;
[[NSNotificationCenter defaultCenter] postNotificationName:UITextViewTextDidChangeNotification object:textView];

Not sure if the explanation is clear, let me know. Thanks!

jessesquires commented 10 years ago

@mrojas :+1: great idea about didReceiveMessage. just pushed those changes. :smile:

mrojas commented 10 years ago

Awesome, thanks!

bassrock commented 10 years ago

awesome job @jessesquires! is the pod spec patch by @robj still valid?

jessesquires commented 10 years ago

@bassrock - hm. probably not. however, you can specify this branch in your podfile.

pod 'JSMessagesViewController', :git => 'https://github.com/jessesquires/MessagesTableViewController.git', :branch => 'version_5_release'