Skip to content

Enhancement/load more messages and maintain scroll position#284

Merged
SD10 merged 7 commits intoMessageKit:developmentfrom
azurechen:enhancement/load-more-messages-and-maintain-scroll-position
Dec 17, 2017
Merged

Enhancement/load more messages and maintain scroll position#284
SD10 merged 7 commits intoMessageKit:developmentfrom
azurechen:enhancement/load-more-messages-and-maintain-scroll-position

Conversation

@azurechen
Copy link
Copy Markdown
Contributor

What does this implement/fix? Explain your changes.

Pull down to load more messages and keep the position.
The example was updated. Reviewers can try the effect at ConversationViewController

Does this close any currently open issues?

#186 Maintain scroll position after loading new messages

Where has this been tested?

Devices/Simulators: iPhone 6, iPhone 7s Simulators

iOS Version: 10

Swift Version: 3.2

MessageKit Version: 0.9.0

@SD10 SD10 requested review from cwalo and nathantannar4 October 26, 2017 02:12
scrollToItem(at: indexPath, at: .bottom, animated: animated)
}

override open func reloadData() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@azurechen Thanks for submitting this PR! Unfortunately, I don't think overriding reloadData is the right approach to achieving this functionality.

I notice this is the second PR you've submitted recently. You should join the MessageKit Slack channel so we can discuss design decisions.

I think some MessageKit users have already implemented this functionality on their own, it would be good to discuss/compare it to what they've done.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi I have joined slack few days ago. Thanks so much.
I have explained my idea on the following comment. I don't think I really override the reloadData method I just extend it.

Copy link
Copy Markdown
Member

@nathantannar4 nathantannar4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @azurechen I like this feature! I agree with @SD10 that we shouldn't override reloadData to get this functionality. Perhaps making a separate function that inserts new messages

@azurechen
Copy link
Copy Markdown
Contributor Author

azurechen commented Oct 26, 2017

I have consider using another method to insert old messages. But let me explain why I think override reloadData is a better idea.

First, base on the pattern of original UICollectionView and UITableView. Developer should use the same messageList to handle the data source. If we use another method to insert old data not directly change messageList will break this pattern.
In other word, update the messageList is necessary, and reloadData should be necessary after developer change the value of messageList.

Second, in a sense I didn't really override the reloadData method because if not trigger the refreshing. The behavior is definitely same as the original reloadData. I just extend the ability.

if !messageLoadMoreControl.isRefreshing {
    super.reloadData()
    return
}

Extend reloadData can make load more function simple and elegant. Only needs two lines can enable load more function.

Register the selector

messageLoadMoreControl.addTarget(self, action: #selector(loadMoreMessages), for: .valueChanged)

And insert older data to the messageList

self.messageList.insert(contentsOf: messages, at: 0)

I have been thinking about how to use a beautiful way to implement it for a few days. I really want to contribute because I use MessageKit in my project even it is still on the beta state.
I may not often discuss on the Slack because my job. But I already join the room and keep following your discussion.

And please try the example, I believe the effect is satisfying.

@cwalo
Copy link
Copy Markdown
Contributor

cwalo commented Oct 26, 2017

@azurechen I thought about this a bit more and I mentioned in slack, but I think a second method - reloadAndMaintainOffset() - might be more ideal. It makes the behavior clear and provides a mechanism for users to use whatever reload/refresh control they want. It would be up to the user to decide to call it or the standard reloadData method.

@azurechen
Copy link
Copy Markdown
Contributor Author

@cwalo I think it is a perfect compromise!
I will take your suggestion and update the PR soon. Thank you.

Copy link
Copy Markdown
Contributor

@cwalo cwalo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't approve until we get some more discussion on this.


// reset the contentOffset after data is updated
self.setContentOffset(CGPoint(
x: self.contentOffset.x + (afterContentSize.width - beforeContentSize.width),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For readability, consider creating a let variable for the new offset and then use that in setContentOffset.


open weak var messageCellDelegate: MessageCellDelegate?

open var messageLoadMoreControl = UIRefreshControl()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not so sure this should live in the collectionview. Perhaps move to MessagesViewController and add a method for adding/removing it. Similar to JSQ in that regard.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree moving it to MessagesViewController make sense. but because of !messageLoadMoreControl.isRefreshing. it have to be put in MessageCollectionView

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. It could also just be called refreshControl and lie in MessagesViewController

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, agree with you both 👍

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly, we don't even need to provide this control? The method is the most important thing. Then the user can hook it up to whatever they want? Need to think about this a little bit more

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a possible issue that different control component has different sliding animation duration. if the animation not stop, it is hard to calculate the right offset.
Do you think we can temporarily keep this control, and provide another interface to user in later version to customize their own refreshControl?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I though an idea. Create a new class name MessageMoreControl but not extends UIRefreshControl.
And user have to setup the component by

messageMoreControl = MessageMoreControl(component: UIRefreshControl())
messageMoreControl.delegate = self

user can choose use UIRefreshControl or customized view

messageMoreControl = MessageMoreControl(component: CustomRefreshView())
messageMoreControl.delegate = self

and provide a MessageMoreControlDelegate for user load more data

protocol MessageMoreControlDelegate {

    func didPullDown(of messageMoreControl: MessageMoreControl)
}

}

public func reloadAndMaintainOffset() {
if !messageLoadMoreControl.isRefreshing {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm waffling between whether or not this method should do any checking of the refresh control or if the user should do it. Otherwise, it should only calculate the new offset and refresh. If this were the case, the user could do any checking they need to, then just call super. @SD10 thoughts?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, the user should probably do this outside of the call to reloadAndMaintainOffset() to determine if the method is called at all. Also, may need to improve method naming on this one 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SD10 could you suggest a name? I think the method name should include reloadData to imply that is a extended method of reloadData

@SD10 SD10 changed the base branch from v0.10.0 to v0.11.0 October 30, 2017 01:55
Copy link
Copy Markdown
Contributor

@cwalo cwalo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question about automaticallyAdjustsScrollViewInsets = true. Otherwise, looks good. 👍

override func viewDidLoad() {
super.viewDidLoad()

automaticallyAdjustsScrollViewInsets = true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this relevant to the PR?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the UIRefreshControl of this example. If not set automaticallyAdjustsScrollViewInsets, the refreshControl will be covered by navigation bar.

@SD10 SD10 changed the base branch from v0.11.0 to development November 2, 2017 03:56
@alijaza
Copy link
Copy Markdown

alijaza commented Nov 15, 2017

Will this be part of v0.11.0?

@SD10
Copy link
Copy Markdown
Member

SD10 commented Dec 4, 2017

@alijaza I'm reviewing this again now

I'm wondering if this functionality can be moved into the MessagesCollectionViewFlowLayout,
then users can toggle a flag to enable/disable this functionality.

See this comment

cc @cwalo What do you think?

@SD10 SD10 closed this Dec 4, 2017
@SD10 SD10 reopened this Dec 4, 2017
@SD10 SD10 changed the base branch from development to master December 17, 2017 05:27
@SD10 SD10 changed the base branch from master to development December 17, 2017 05:28
@SD10 SD10 removed the under review label Dec 17, 2017
@SD10 SD10 merged commit 67e6998 into MessageKit:development Dec 17, 2017
@SD10
Copy link
Copy Markdown
Member

SD10 commented Dec 17, 2017

Thank you for contributing to MessageKit! I've invited you to join the MessageKit GitHub organization - no pressure to accept! If you'd like more information on what that means, check out our contributing guidelines and join the MessageKit Slack channel. Feel free to reach out if you have any questions! 😃

SD10 added a commit that referenced this pull request Dec 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants