steve228uk / MessengerKit

:speech_balloon: A UI framework for building messenger interfaces on iOS
MIT License
1.48k stars 129 forks source link

Custom Message Formats #7

Closed svm1 closed 5 years ago

svm1 commented 6 years ago

Hi @steve228uk,

Amazing framework! A small question from someone new to iOS dev. I wanted to use MSGMessageBody with custom content (neither text, emoji, image, nor video) but am unsure as to what should be modified to implement this. For instance, I want to have a message bubble with a clickable UIButton inside it. Do you think you could help point me towards what/where I should modify to add such custom message formats?

steve228uk commented 6 years ago

Do you have an example as to what the button would do or look like? My initial thought is that using text that could control the title or action that you’d need.

Though I think there is a case here for a new custom type that accepts Any type.

svm1 commented 6 years ago

Thanks for the response. Sure, my ultimate goal is to have clickable text that looks like a link, but is not a link to a webpage - instead, clicking on the text should trigger an in-app action. I was thinking that I would need a custom type that can store both the text that should be displayed in the message bubble (e.g "Hello") as well as the event that should be triggered on press (e.g a popup).

steve228uk commented 6 years ago

Yeah that makes sense. I'll look to add an additional case in that will be accessible by custom message cells. For now you could use a delimiter and split it to get the title and the event e.g. "Hello|popup". Not ideal but for the time being it should work.

svm1 commented 6 years ago

Sounds great. Would there be no way for me to add this kind of custom cell myself though in the meantime? I was trying to see how the text/emoji etc. are defined to replicate them, but could't quite find where they were defined and used.

steve228uk commented 6 years ago

Every MSGMessageCell has its message property set. In here an if case let is done to check the type of message.

https://github.com/steve228uk/MessengerKit/blob/master/MessengerKit/Collection%20View/Cells/Emoji/MSGEmojiCollectionViewCell.swift#L15-L22

It should just be a case of adding custom(Any) to the MSGMessageBody but I don't have time to do this tonight. Feel free to experiment and submit a PR if you have any success 😊

https://github.com/steve228uk/MessengerKit/blob/master/MessengerKit/Models/MSGMessageBody.swift

svm1 commented 6 years ago

Thank you! 😃I'll play around and let you know!

Just one more question if you don't mind - I was trying to add another button beside the "send message" button, but was unable to find how to do so. I was looking in MSGInputView.swift but could not replicate how the "send" was created, do you think you could briefly point me in the right direction when you get a chance?

steve228uk commented 6 years ago

Currently MSGInputView only includes a send button by default but you should be able to add anything you'd like if you're going to handle the action yourself. The easiest way to achieve this is to create a new XIB and add everything in there. This is how both the Travamigos and iMessage styles work.

svm1 commented 6 years ago

Gotcha. Very sorry for all the q's, please excuse my incompetence here! May I just ask what is an XIB?

steve228uk commented 6 years ago

XIB/NIB is an interface builder file.

svm1 commented 6 years ago

Thank you for all the answers! I appreciate your time.

gersonjanhuel commented 6 years ago

Success with "add custom button to the inputView" sir ? @svmadiraju

Hope you can share some of your code, really appreaciate it!

steve228uk commented 6 years ago

@svmadiraju I've added a custom(Any) case to the MSGMessageBody as well as two new identifiers outgoingCustom and incomingCustom that should help here.

Alternatively you could override collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) and set the message, delegate etc. per cell yourself.

steve228uk commented 6 years ago

Will add an example later today or tomorrow if I get time.

svm1 commented 6 years ago

Wow, thanks @steve228uk! That was fast, let me take a look and play around with it!

Small side note, do you know how to make a new .XIB file for use correctly? Every time I do so and change the file name in MSGImessageInputView, I get "Could not load NIB" errors. Looked it up and not sure how to fix, is there a better way to be using a custom XIB?

steve228uk commented 6 years ago

@svmadiraju You'll need to create a custom UIView and Nib, wire them up and then set the in your style assign it to the inputView variable.

https://github.com/steve228uk/MessengerKit/wiki/Creating-a-Custom-Style

svm1 commented 6 years ago

Hi @steve228uk, Very sorry to have been bothering you with all this confusion, but I am still a bit lost as to how to modify the UI to add custom UI elements. I referred to the documentation you linked and studied the steps outlined to creating a new style, but all of those seem to be regarding modifying the look of the existing elements.

I'm pretty sure my thick skull is just missing basic something here, but I can't seem to understand what I should modify to add custom elements to the existing style. My incompetence would truly appreciate some guidance in this direction. (Just to clarify, I am trying to modify the message text field + send button "input view" component.)

gersonjanhuel commented 6 years ago

@svmadiraju Do you mean custom the message bubble ? I can help share my code. Did success with that.

About custom "Input View" same with you, still confuse.

steve228uk commented 6 years ago

@svmadiraju @gersonjanhuel For the input view you'll need to subclass the MSGInputView, override the nib property to return the nib you're using for the design. You nib should include an MSGPlaceholderTextView and a button. Take a look at the existing nibs for some guidance here.

svm1 commented 6 years ago

Hi @steve228uk,

Just following up on the earlier issue I was struggling with. First of all, thank you very much for the clarification. I spent a lot of time with the code and now have a much better understanding of NIBs and all the major files used in MessengerKit and how they work together.

I created a new custom InputView as a subclass of MSGInputView as well as a new NIB file with an MSGPlaceholderTextView, a button, and my own custom elements. I overrode the nib property in my new MSGInputView subclass with the name of the new NIB file I created. I then set the inputView property in my Custom Style (subclass of MSGMessengerStyle) to the new InputView I created.

However, I am receiving an "Could not load nib in bundle 'nsbundle" error even when it seems that everything is done properly. When I set the inputView property in my Custom Style to an existing InputView (iMessage/Travamigos) the code runs fine and uses that InputView in my Custom Style - so it is definitely some problem with my custom NIB file.

I spent a lot of time researching this error but can't seem to find anything up-to-date and relevant that could help, so I was wondering if you might be familiar with it. Is there anything further I need to do to link my custom NIB with the project?

steve228uk commented 6 years ago

@svmadiraju Could you paste the nib override? It should look something like

UINib(nibName: "YourCustomNib", bundle: nil)
gersonjanhuel commented 6 years ago

@svmadiraju

Here my custom inputView class is ChatInputView

Is it correct to do it like that ?

then I got exception textView is nil...

screen shot 2018-07-10 at 4 07 52 pm
steve228uk commented 6 years ago

@gersonjanhuel It looks like you haven't linked your UINib to the textView @IBOutlet

gersonjanhuel commented 6 years ago

its already linked to MSGInputView... @steve228uk

My steps :

screen shot 2018-07-10 at 8 13 24 pm
steve228uk commented 6 years ago

@gersonjanhuel It should be linked to your new subclass. Try removing the reference and creating it again.

gersonjanhuel commented 6 years ago

when I create new outlet in my new subclass... its error... says textView cannot be override... @steve228uk

steve228uk commented 6 years ago

@gersonjanhuel You shouldn't need to create the outlet in the file itself as it will be auto-inherited from the super. Right click on the button or text view and drag the outlet to the "Chat Input View" in the left sidebar. You should be able to link it to the existing outlet there.

svm1 commented 6 years ago

@steve228uk, Thank you very much for the prompt responses. Sure, here is my nib override:

override open class var nib: UINib? {
        return UINib(nibName: "CustomNib",
                     bundle: nil)
}

For the sake of testing, I am testing it without any other UI elements right now - specifically, all I did to make this current custom NIB is take your existing MSGImessageInputView NIB and graphically shrink the text field down in the NIB editor.

Here is a screenshot of said Custom NIB:

screen shot 2018-07-10 at 10 21 03 am

If it helps, here is the error output:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
reason: 'Could not load NIB in bundle: 'NSBundle </Users/svm/Library/Developer/CoreSimulator/Devices/A6C668C8-5F65-4C7F-97BD-DF4935645FA1/data/Containers/Bundle/Application/F7BC95F9-E347-4BEC-8CB6-596FDA97C8FF/MessengerKit_Example.app> (loaded)' with name 'MSGImessageNewNibInputView''

The error leads me to believe the problem is related to the project not recognizing my NIB or that something further needs be done to link my NIB with the rest of the project.

Once again, I really appreciate you taking the time to go through this, it means a lot. Please let me know if there is anything else I can provide to make it easier.

Just to clarify once again, all I want to do is add a custom button beside the Send button.

gersonjanhuel commented 6 years ago

@steve228uk not sure what do you mean by : "Right click on the button or text view and drag the outlet to the "Chat Input View" in the left sidebar."

can you provide example code for this ? would really appreciate it

gersonjanhuel commented 6 years ago

Ok got it! Succesfully wired them up... but I cant do :

override open class var nib: UINib? { return UINib(nibName: "CustomInputView", bundle: nil) }

gersonjanhuel commented 6 years ago

have any luck with the custom Input View ? @svmadiraju

JStrawn commented 5 years ago

When I try to subclass MSGInputView, I get an Overriding non-open class var outside of its defining module error.

I tried subclassing MSGImessageInputView, but even though my view has a text view and a send button connected to the custom InputView, I get a crash when setting the textfield delegate int MSGInputView. Any advice for making a custom InputView? Thanks

sjoness commented 5 years ago

@svmadiraju @gersonjanhuel @JStrawn I do realise that this thread has been dead for a while but I'll still chip in. These issues are due to the nib, textView and sendButton properties being public access level. Public class members can only be overridden by subclasses defined in the module they are defined in, therefore the access level needs to be changed to open for subclassed MSGInputView's to work. I've submitted a PR #24 for this change and it should hopefully be merged soon 👍

sjoness commented 5 years ago

@steve228uk Pretty sure this can be closed now since you added the custom(Any) MSGMessageBody case and the MSGInputView subclassing issue has been resolved.