Open Source & Free

46. Push - Client Side Integration

Module 13: Creating a Facebook Clone Transcript it’s now time to map the push support into the client side to do that we need to implement the push callback interface in the main class of our app we can only implement push callback in the main class nowhere else register push should be invoked with every launch to refresh the push key as it might change we use call serially to defer this so we don’t block the start method the push method is invoked with the text of the push in that case we call the refresh method to update the ui we’ll discuss that method soon the device id isn’t the push key it’s the os native push value normally you would have no need for it as it’s here for compatibility only the push key value is only guaranteed once this callback is invoked if the push key changed since the last time we update the push key in the server we’ll cover this method soon there isn’t much we can do in the case of an error so right now i only log it in some cases you can show a ui notification but make sure not to do it from this method as it’s invoked early in the app launch cycle and that might impact the ui in odd ways just store the error details and show a notice later on next we need to cover the server api changes and refresh method we’ll start with the former in the sign up or login method of the server api we need to invoke register push after the successful login this is important for the first time the user logs in to the app next we need to map the update push key method this is just a simple call with one argument we return a boolean value to indicate that the call worked that’s it ui controller needs a bit of work too first we need to add a field for the main form instance this will allow us to refresh the main form as notifications come in the method is now updated this method is now updated with the new main field so we can refresh the ui refresh delegates into the main form instance it’s possible that the push method is invoked before loading completed so main would be null in that case this isn’t a problem since main would be created with fresh data anyway again with mainform we need to take fields that were in the constructor before and move them to the class level so we can refresh them once we went through that with the refresh method is easy if we are currently viewing the news feed and we aren’t minimized a refresh might create a bad user experience if we are minimized or in a different tab we can refresh the ui immediately this refresh method is from infinite container the same logic applies to the notification code this method shows a toast bar offering the user a refresh if he taps the toast bar we use this to prompt the user instead of refreshing automatically with that push should work and refresh when applicable

Codename One

1. Getting Started

Module 14: Creating a WhatsApp Clone Transcript in this module we’ll build a rudimentary whatsapp clone i’ll take a very different path when compared to previous cloned applications here we’ll talk about that and these things in the next few slides the first thing i’d like to go into is that this clone isn’t pixel perfect it’s a fast and dirty clone i’ll focus only on the basic text sending functionality and won’t go into nearly as much as detail as i did in the other clones frankly it’s not necessary the functionality is simple once you understand the facebook clone i skipped a lot of the core features mostly due to time but also because these features are covered in the facebook clone and re-implementing them for yet another clone would have been redundant i’ll only focus on these forms i won’t implement everything here either since we already implemented sms verification in the facebook loan i’ll use the sms activation library however i’ll use server side authentication for that library for extra security whatsapp doesn’t use passwords i considered using the phone number as the id which seems to be what they are doing i ended up using a regular id though there is an authorization token which i will discuss later like other clones i use spring boot again that makes this familiar and allows me to grab some code from the other projects the database will read mysql again for the same reason i’ll store data as json locally instead of sqlite this makes it easy to use and debug the code that might be something worth changing if you are building this for scale i’m still using web services for most of the functionality they are still easier to work with than web sockets however messaging is the ideal use case for websockets and i’m using it for that exact purpose when the websocket is closed which would happen if the app isn’t running or is minimized i use push push is used strictly as a visual medium to notify the user of a new message when sending and receiving data in websockets i use json in the past i used a binary websocket and i wanted to show how this approach works as well so let’s start by creating the spring boot project for the server i’m assuming you went through the previous modules and i won’t repeat myself too much you can use the spring boot initializer which i used to create this pom file i just defined a new project with this package for java 8. we’ll use jpa to communicate with the mysql database we use jersey for pojo json serialization the security package allows us to encrypt credentials into the database it has a lot of other features but they aren’t as useful for us we need web services support too and web sockets to implement the full communication protocol the underlying database is mysql so we need the right drivers for that and finally we need the server side twillow library to implement sms support on the server this will be used for the activation code functionality next we need to create the client application which i create as whatsapp clone i use the default native and bare bones settings in the ide i pick the com codename1.whatsapp package nothing special next we’ll go into the classes that implement the client functionality

Codename One

2. Client to Server Abstraction

Module 14: Creating a WhatsApp Clone Transcript we’ll jump into the client functionality from the server connectivity class I won’t start with the UI and build everything up but instead go through the code relatively quickly as I’m assuming you’ve gone through the longer explanations in the previous modules like before the server class abstracts the back end I’ll soon go into the details of the other classes in this package which are property business object abstractions as a reminder notice that I import the CN class so I can use shorthand Syntax for various apis I do this in almost all files in the project right now the debug environment points at the local host but in order to work with devices this will need to point at an actual URL or IP address as I mentioned before we’ll store the data as Json in storage the file names don’t have to end in dot Json I just did that for our convenience this is a property business object we’ll discuss soon we use it to represent all our contacts and ourselves this is the current websocket connection we need this to be Global as we will disconnect from the server when the app is minimized that’s important otherwise battery saving code might kill the app this flag indicates whether the websocket is connected which saves us from asking the connection if it’s still active if we aren’t connected new messages go into the message queue and will go out when we reconnect the user logged into the app is global the init method is invoked when the app is loaded it loads the global data from storage and sets the variable values normally there should be data here with the special case of the first activation if this is the first activation before receiving the validation SMS this file won’t exist in that case we’ll just initialize the contact cache as an empty list and be on our way assuming we are logged in we can load the data for the current user this is pretty easy to do for property business objects if there are messages in the message queue we need to load them as well this can happen if the user sends a message without connectivity and the app is killed contacts are cached here the contacts essentially contain everything in the app this might be a bit wasteful to store all the data in this way but it should work reasonably even for relatively large data sets this method sends the content of the message queue it’s invoked when we go back online these methods are shorthand for get and post methods of the rest API they force Json usage and add the auth header which most of the server-side apis will need that lets us write shorter code the login method is the first server sign method and doesn’t do much it sends the current user to the server then Saves The Returned instance of that user this allows us to refresh you the data from the server we pass the current user as the body in an argument notice I can pass the property business object directly and it will be converted to Json in the response we read the user replace the current instance and save it to disk sign up is very similar to login in fact it’s identical however after signup is complete you still don’t have everything anything since we need to verify the user so let’s skip down to that on the server signup triggers an SMS which we need to intercept we then need to send the SMS code via this API only after this method returns okay our user becomes valid update is practically identical to the two other methods but sends the updated data from the client to the server it isn’t interesting send message is probably the most important method here it delivers a message to the server and saves it into the Json storage here we have the time in which a specific contact last chatted this allows us to sort the contacts based on the time a specific contact last chatted with us this sends the message using a web service the message body is submitted as a chat message business object which is implicitly translated to Json initially I sent messages via the websocket but there wasn’t a big benefit to doing that I kept that code in place for reference the advantage of using websocket is mostly in the server side where the calls are seamlessly translated sorry the advantages of using web service is mostly that if we are offline the message is added to the message queue and the content of the queue is saved this method binds the websocket to the server and handles incoming and outgoing messages over the websocket connection this is a pretty big method because of the inner class within it but it’s relatively simple as the inner class is mostly trivial the bind method receives a callback interface for various application Level events for instance when a message is received we’d like to update the UI to indicate that we can do that via the Callback interface without getting all of that logic into the server clause here we create a subclass of websocket and override all the relevant callback methods skipping to the end of the method we can see the connection call and also Auto reconnect method which automatically tries to reconnect every five seconds if we lost the websocket connection let’s go back to the Callback method starting with on open this method is invoked when a connection is established once this is established we can start making websocket goals and receiving messages we start by sending an init message this is a simple Json message that provides the authorization token for the current user and the time of the last message received this means the server now knows we are connect connected and knows the time of the message we last received it means that if the server has messages pending it can send them now next we send an event that we are connected notice I used calls serially to send it on the EDT since these events will most likely handle GUI this makes sense finally we open a thread to send a ping message every 80 Seconds this is redundant for most users and you can remove that code if you don’t use cloudflare however if you do then cloudflare closes connections after 100 seconds of inactivity that way the connection isn’t closed as cloudflare sees that it’s active cloudflare is a Content delivery Network we use for our web properties it helps scale and protect your domain but it isn’t essential for this specific deployment still I chose to keep that code in because this took us a while to discover and might be a stumbling block for you as well when a connection is closed we call the event again on the EDT and mark the connected flag appropriately all the messages in the app are text-based messages so we use this version of the message callback event to handle incoming messages technically the messages are Json strings so we convert the string to a reader object then we parse the message and pass the result into the property business object this can actually be written in a slightly more concise way with the from Json method however that method didn’t exist when I wrote this code now that we parsed the object we need to decide what to do with it we do that on the EDT since the results would process uh to to impact the UI the typing flag allows us to send an event that a user is typing I didn’t fully implement this feature but the Callback and event behavior is correct another feature that I didn’t completely finish is the viewed by feature here here we can process an event indicating there was a change in the list of people who saw a specific message if it’s not one of those then it’s an actual message we need to start by updating the last received message time I’ll discuss update messages soon it effectively stores the message act message acknowledges the server to the server that the message was received this is important otherwise a message might be resent to make sure we received it finally we invoke the message received callback since we are already within the call serially we don’t need to wrap this too we don’t use binary messages and most errors would be resolved by o to reconnect still it’s important to at least log the errors the update method is invoked to update messages in the chat first we Loop over the existing contacts to try to find the right one once we find the contact we can add the message to the contact the find method finds that contact and we add a new message into the database this is invoked when a contact doesn’t already exist within the list of contacts we already have cached the method closes the websocket connection it’s something we need to do when the app is suspended so the OS doesn’t kill the app we’ll discuss this when talking about the lifecycle methods later the contacts are saved on the contacts grid we use this helper method to go into the helper thread to prevent race conditions fetch contacts loads the contacts from the Json list or the device contacts since this can be an expensive operation we do it on a separate context thread which is an easy thread easy trades let us send tasks to the thread similarly to call serially on the EDT here we lazily create the easy thread and then run fetch contacts on that thread assuming the current easy thread is null if the thread already exists we check whether we already are on the easy thread assuming we aren’t on the easy thread we call this method again on the thread and return all the following lines are now guaranteed to run on one thread which is the easy thread as such there are effectively thread safe and won’t slow down the EDT unless we do something that’s very CPU intensive we already have the data we use called serial if we already have the data we use call Siri on idle this is a slow version of call serially that waits for the EDT to reach idle state this is important for performance a regular call serially might occur when the system is animating or in need of resources if we want to do something expensive or slow it might cause choking of the UI call Syria on idle will delay the call serially to a point where there are no pending animations or user interaction this means that there is enough CPU to perform the operation if we have a Json file for the contacts we use that as a starting point this allows us to store all the data in one place and mutate the data as we see fit we keep the contacts in a contacts cache map which enables fast access at the trade-off of some Ram this isn’t too much since we store the thumbnails as external jpegs once we loaded the core Json data we use call serially to send the event of loading completion but we aren’t done yet we Loop over the contacts we loaded and check if there is an image file matching the contact name assuming there is we load it on the context thread and set it to the contact this will fire an event on the property object and trigger a repaint asynchronously if we don’t have a Json file we need to create it and the place to start is the contacts on the device get all contacts fetches all the device contacts the first argument is true if we only want contacts that have phone numbers associated with them this is true as we don’t need contacts without phone numbers the next few values indicate the attributes we need from the contacts database we don’t need most of the attributes we only need we only fetch the full name and phone number the reason for this is performance fetching all attributes can be very expensive even on a fast device next we Loop over each contact and add it to the list of contacts we convert the built-in contact object to chat contact and the process for every entry in the contacts we need to fetch an image we can use calls serially on idle to do that this allows the image loading to occur when the user isn’t scrolling the UI so it won’t noticeably impact performance once we load the photo into the object we save it to storage as well for faster retrieval in the future this is pretty simplistic code proper code would have scaled the image to a uniform size as well this would have saved memory finally once we are done we save the contacts to the Json file this isn’t shown here but the content of the photo property is installed to the Json file to keep the size minimal and loading time short once loaded we invoke the callback with the proper argument when we want to contact a user we need to First make sure he’s on our chat platform for this we have the find registered user server API with this API we will receive a list with one user object or an empty list from the server this API is asynchronous and we use it to decide whether we can send a message to someone from our contacts this is a similar method that allows us to get a user based on the user ID instead of a phone if we get a chat message that was sent by a specific user we will need to know about that user this method lets us fetch the method metadata related to that user the chats we have open with users can be extracted from the list of contacts since every contact has its own chat thread so to fetch the chats we see in the main form of the WhatsApp UI we need to First fetch the contacts as they might not have been loaded yet we Loop over the contacts and if we had activity with that contact we add him to the list in the response but before we finish we need to sort the responses based on activity time the sort method is built into Java Collections API it accepts a comparator which we represented here as a Lambda expression the comparator Compares two objects in the list to one another it returns a value smaller than zero to indicate the first value is smaller zero to indicate the values are identical and More Than Zero To indicate the second value is larger The Simple Solution is sorry smaller The Simple Solution is subtracting the time values to get a valid comparison result we saw the ack call earlier this stands for acknowledgment we effectively acknowledge that the message was received if this doesn’t go to the server the server doesn’t know if a message reached its destination finally we need this method for push notification it sends the push key to the device of the device to the server so the server will be able to send push messages to the device

Codename One

3. The Model Package

Module 14: Creating a WhatsApp Clone Transcript the next step are the other classes within the model package the rest is relatively trivial after the server class this is the callback interface we used within the server class it’s pretty trivial i added some methods for future enhancement too the first two methods inform the observer that the server is connected or disconnected message received is invoked to update the ui based on the new incoming message the last two callbacks aren’t really implemented but they allow us to update the ui if a user is typing in a chat the message viewed event similarly indicates if a user viewed the message this can provide an indicator in the ui that the message was seen chat contact is a property business object that stores the content of a specific contact entry i chose to use unique ids instead of using the phone as an id this was something i was conflicted about i eventually chose to use an id which i think is more secure overall it would also support the option of changing a phone number in a future in the future or using an email as the unique identifier local id should map to the id in the contacts this allows us to refresh the contact details from the device address book in the future the phone property is pretty obvious the photo property stores the picture of the contact there is a lot to this property so i’ll discuss it in more details soon these are the common attributes for name and tagline used in whatsapp for simple simplicity i chose to use a full name and ignored nuances such as first lost middle initial etc the token is effectively our password to use the service since there is no login process a token is generated on the server as a key that allows us to use the service a chat contact can also serve as a group i didn’t fully implement this logic but it’s wired almost everywhere in this case we have two sets for members of the group and the admin of the group these sets would be empty for a typical user the this property allows us to mute a chat contact so we won’t see notifications from that contact if this is a group then it was created by a specific user the id of that user should be listed here the creation date is applicable to both groups individual users this is the timestamp of the last message we received from the given user we saw this updated in the server class we use use this to sort the chats by latest update chat message is the property business object that contains the content of the message here we saw the actual chats we had with the contact or group as i mentioned before photo is installed in json when we save the contact to keep the size low we save the contact image in a separate file and don’t want too much noise here the app has two thumbnail images one is slightly smaller than the other and both are rounded to keep the code generic i used arrays with the detail and then used two sizes one small size maps to the zero offset and the array and the large size maps to the one offset here are the sizes of these two images in millimeters images are masked to these sizes masking allows us to round an image in this case we generate placeholder images which are used when an image is unavailable this method creates a mask image of a given size and pixels a mask image uses black pixels to represent transparency and white pixels to represent the physical visible opacity so where we draw a black rectangle image with a white circle in the center when we apply this mask to an image only the portion represented by the white circle will remain the placeholder image is used when no image is defined again we create this based on size and pixels we create a gray image and then draw on it using white we use the material font to draw the image of a person onto this image this method gets the image represented by the contact in theory i could have used the photo property and overridden get to implement this i thought this is a simpler approach here we lazily initialize the arrays of the mask image for larger or larger small images we create the mask images then convert the mask image to mask object finally we create the placeholder image if the photo is null i return the placeholder image instead of using the photo object otherwise we fill the image into the size of the mask and apply the mask to create a round object fill scales the image so it’s cropped while filling the exact boundaries given it doesn’t distort the aspect ratio of the image like a typical scale operation would the final public methods and variables cache the small and large image appropriately they are the publicly exposed apis for this functionality

Codename One

4. The Main Class

Module 14: Creating a WhatsApp Clone Transcript there is still one other class within the model package once we finish that we’ll go to the main class the chat message class is another property business object but one that’s even simpler than the last one this is the author of the message since we use ids and not phones this might become an issue so we need to keep track of both sent to can be important as this message might have been sent to a group and not directly to our current user the timestamp of the message and the actual text of the message are the main payload attachments aren’t fully implemented the general idea is a url of the attachment mapping to a mime type so we can represent it in the ui as image slash video audio or document the list of people who viewed the message which can be more than one for a message sent to a group the typing message is a special type of message that we don’t currently send but it can be sent pretty easily and just update the ui that the user is typing to this chat this is the final property in this class which is relatively simple with that long detour out of the way let’s go back to the main class as you can see i left most of the code intact and kept it as the default the first piece of code you will see that isn’t part of the default code is this line to initialize the server and load the saved data there is also the push interface which we need to implement to receive push callbacks that leads us directly to the first method from that interface we don’t need to implement this method since we use push only as a visual medium and rely on web sockets to carry the actual data push is inherently unreliable and might perform badly it places limitations on the type of data you can send we have more control over web sockets we use push only when the app is minimized the one method we need to implement from the push interface is the registered for push corbett when this callback is invoked we need to send the push key to the server this is important notice that the push key isn’t the device id there are different values don’t confuse them the sms verification class is an abstract class from the sms verification cn1 lib it lets us move some of the functionality of that library into the server the first method is the send sms code method it sends an sms mesh message to the given phone number on the server it invokes the signup call which triggers an sms to that phone number this callback is invoked as part of the signup process when the user types in or the system intercepts a phone number this callback is invoked it sends the verification string to the server side and returns the result based on that the message listener allows us to track messages from the server such as connect incoming messages etc a lot of this isn’t implemented as we don’t need it right now but it could be useful for the ui as it evolves one thing we do implement here is the message received api there isn’t much going on in this method though if the current form is the chat form then we need to check if we are currently in the chat form with the sender of the incoming message assuming this is the case we can add this message to the ui regardless we need to refresh the main ui of the chat list container since the order to the contacts will change next we have the start lifecycle method you will notice that we invoke bind message listener even when we restore a running app as you might recall we close the websocket connection when the app is minimized this effectively restores that connection when the app is restored back to normal the this call happens when the app is launched in a cold start if the phone number isn’t set this is the first activation and we need to set up a new user the activation form api builds the data and you are using a builder pattern where every method adds to the resulting form first we allocate the activation form with the title sign up when we then determine that we want a six digit activation code instead of the default four digit code we finally show the activation ui this accepts two arguments the second argument is the sms verification subclass we discussed earlier it sends the sms details to the server which issues an sms it then performs verification on the server which is more secure than client-side verification the first argument is a callback that’s invoked when the activation is completed it’s invoked with a phone number in the result here we store the new phone number to the preferences then show the main form ui if the user was already registered we show the main form directly we discussed the bind method before so the last piece is the register push core this is an essential part of the push notification support finally we added close websocket code to the stop method this implements the logic of stopping the websocket connection when the app is minimized

Codename One

5. Main Form

Module 14: Creating a WhatsApp Clone Transcript now that we implemented the model code and the lifecycle code we are almost finished we are down to ui code and css we start with the main form which covers the list of chat elements as is the case with all the forms in this app we derive from form for simplicity the main body of the form is a tabs component that allows us to switch between camera status and calls camera kit is used to implement the camera ui but due to a regression in the native library this code is currently commented out there are the three tab containers we make use of them in the scrolling logic later the main form is a singleton as we need a way to refresh it when we are in a different form the form itself uses a border layout to place the tabs in the center we also save the form instance for later use we hide the tabs it generally means that these aren’t actually tabs they are buttons we draw ourselves the reason for that is the special animation we need in the title area we add the tabs and select the second one as the default as we don’t want to open with the camera view instead of using the title we use title component which may takes over the entire title area and lets us build whatever we want up there i’ll discuss it more when covering that method the back command of the form respects the hardware back buttons and some devices and the android native back arrow here we have custom behavior for the form if we are in a tab other than the first tab we need to return to that tab otherwise the app is minimized this seems to be the behavior of the native app the calls container is a y-scrollable container this is simply a placeholder i placed here a multi-button representing incoming outgoing calls and a floating action button the same is true for the status container this isn’t an important part of the functionality with this tutorial you might recall that we invoke this method from the main ui to refresh the ongoing chat status we fetch up to date data from storage this is an asynchronous call that returns on the edt so the rest of the code goes into the lambda we remove the old content as we’ll just read it we loop over the contacts and for every new contact we create a chat multi button with the given name if there is a tagline defined we set that tagline we also use the large icon for that per person if the button is clicked we show the chat form for this user the chats container is the same as the other containers we saw but it’s actually fully implemented it invokes the refresh chats container method we previously saw previously saw in the order in order to fill up the container and the floating action button here is actually implemented by showing the new message form [Music] camera support is currently commented out due to a regression in the native library however the concept is relatively simple we use the tab selection listener to activate the camera as we need the overflow menu is normally implemented in the toolbar but since i wanted more control over the toolbar area i chose to implement it manually in the code i used buttons with the command uiid and container with the command list uid to create this ui i’ll discuss the css that created this in the next lesson i create a transparent dialog by giving it the container ui id i place the menu in the center the dialog has no transition and disposed if the user taps outside of it or uses the back button this disables the default darkening of the form when a dialog is shown this version of the show method places the dialog with a fixed distance from the edges we give it a small margin on the top to take the state status bar into account then use left and bottom margin to push the dialog to the top right side this gives us a lot of flexibility and allows us to show the dialogue in any way we want this method creates the title component for the form which is this region the method accepts the scrollable containers in the tabs container this allows us to track scrolling and seamlessly fold the title area the title itself is just a label with a title ui id it’s placed in the center of the title area border layout if we are on ios we want the title to be centered in that case we need to use the center version of the border layout the reason for this is that center alignment doesn’t know about the full layout and would center based on available space it would ignore the search and overflow buttons on the right when centering since it isn’t aware of other components however using the center alignment and placing these buttons in the east solves that problem and gives us the correct title position a search and overflow commands are just buttons with the title and the title ui id we already discussed the show overflow menu method so this should be pretty obvious we just placed the two buttons in the grid i chose not to use a command as this might create a misalignment for the this use case and won’t have saved on the amount of code i had to write these are the tabs for selecting camera chat etc there are just toggle buttons which in this case are classified as radio buttons this means only one of the radio buttons within the button group can be selected we give them all the subtitle ui id which again i’ll discuss in the next lesson we use table layout to place the tabs into the ui this allows us to explicitly determine the width of the columns notice that the table layout has two rows the second row of the table contains a white line using the side title underline ui id this line is placed in row one and column one so it’s under the chats entry when we move between tabs this underline needs to animate to the new position here we bind the listeners to all four buttons mapping to each tab when a button is clicked we select the appropriate tab the next line two lines implement the underline animation effect that we see when we click a button notice how the line animates to the right tab button to achieve this we remove the current white line and add it back to the toggle container in the right position we reset the height of the title in case it was shrunk during scrolling and we finally update the layout with an animation which performs the actual line move animation the previous block updated the tab selection when we select a button this block does the opposite it updates the button selection when we swipe the tabs it uses a tab selection listener if the button isn’t selected then we need to update it [Music] again we need to reset the title size next we select the button that matches the tab [Music] finally we perform the animation of moving the underline between tabs notice that this is almost identical to the previous animation code only in this case it’s triggered by dragging the tabs instead of the button click events the last two lines in this method are the bind folding call which we’ll discuss soon and the box layout y which wraps the two containers as one the bind folding method implements this animation of the folding title it’s implemented by tracking pointer drag events and shrinking the title when the pointer is released we need to check if the title shrunk enough to minimize it minimize or not enough so it would go back to the full size if the title area height is different from the original height it means we are in the process of shrinking the title in that case we need to decide whether the process is closer to the finish line or to the start it’s less than halfway to the height of the title we reset the preferred size of the title area that means the title area will take up its original original preferred size and go back to full height otherwise we set the title area height to zero so it’s effectively hidden regardless of the choice we made above we show it using an animation we detect the drag operation by binding a scroll listener to the three scrollable containers i could have used pointer drag listeners but they might generate too much noise that isn’t applicable [Music] i chose to make a special case for the tensile drag effect the tensile effect in is the ios scroll behavior where a drag extends beyond the top most part then bounces back like a rubber band this can cause a problem with the logic below so i decided that any scroll position above 10 pixels should probably show the full title now that all of that is out of the way we can calculate the direction of the scroll and shrink or grow the title area appropriately if the diff is larger than zero then the title area should grow we’re setting the preferred height to the diff plus the preferred height but we make sure not to cross the maximum height value we then revalidate to refresh the ui a negative diff is practically identical with the exception of making it zero or larger instead of using the minimum value we use the max method and with that the title folding is implemented the one last method in the class is this we use a custom toolbar that disables centered title the centered title places the title area in the center of the ui and it doesn’t work for folding we need to disable it for this form so the title acts correctly on ios

Codename One

6. Theme CSS

Module 14: Creating a WhatsApp Clone Transcript now that we looked at the first ui form let’s take a short detour via the css for the app i chose to go with css as it’s much easier for tutorials i can use sources instead of multiple screenshots to explain an idea the first selector is a constants selector it lets us define theme constants here we include two basic values that most apps should include include native ball indicates that we want the theme to derive from the native theme as a starting point this is essential as it defines a lot of important things such as the spacing on top of ios devices etc the scroll visible ball constant it hides the scroll bars that might show in some os’s pop-up dialog appears as an arrow dialogue on in ios but other os’s don’t implement it the pop-up dialog is used in the sign-up process for picking the country of sms verification the background color of the pop-up is white and implied implicitly defined as opaque we have a subtle rounded corners with a radius of one millimeter on the dialog you will notice zero margin as the dialog touches the edges but two millimeters in padding which space the content a bit from its edges label is pretty standard so i won’t spend too much time on that it’s just a two and a half millimeter light font multiline 1 is used to describe the first line of the multi button there isn’t much here just a light slightly larger font the one thing to notice is the zero padding on the bottom so the first line and the next line will be close together multi-line 2 is pretty similar to multiline one only with a slightly smaller font notice that the blue color of the text is derived from the native theme and isn’t declared here also also notice the one pixel grey border at the bottom of the multi-line multi-line three and four have zero padding and margin this removes potential error in spaces from the list of buttons the whole multi button is styled here to have a white background with no margin or padding notice that border is explicitly defined as none this is important as the multi button contains a line border and some native themes that would collide with the shorter border we want in this case the toolbar defines the background and the top of the form we give it a one pixel bottom border which is pretty similar to the border defined in the native app it’s very subtle when styling the title we should usually style the commands as well so they have similar proportions and alignment subtitle represents the four buttons below the title they are similar but have an off-white color are slightly smaller and are center center aligned toggle buttons use the press state to indicate selection in which case we want them to be white the subtitle underline is the animated small thin white line below the buttons this draws the full content of the component chat form uses the image as a background image notice the source dpi 0 argument which means we don’t want to use multi image for this for this specific case this just sets the color of the floating action button we use the text field in the signup form it’s added by the sms activation cn1 lib there’s nothing special about it however the chat text field is a separate component it uses a pull border to wrap its content technically this is a container that tracks the actual text field but it’s still perceived as a text field the icons within the text field are just simple font image icons with a specific color and very little margin the text field hint is just a great text for the text field and the record button has round border similar to the floating action button nothing special other than a bit of padding and margin to position it properly chat time represents the hour next to the message within the chat bubble it’s just gray and smallish we make sure it’s transparent so it can work on white or green backgrounds the same goes for the chat text with larger black font it’s still transparent for the same reason the bubble of the chat is implemented in code as a custom border i thought about using a nine piece border and this seemed like a better option i use margin on the right side to prevent the bubble from going too deep into the other side this seems close to what whatsapp is doing in their app the same is true for chat bubbles right with a different color and direction of the margin which is now spaced on the left side the command list is the style of the overflow menu i use box shadow which unfortunately produces a nine piece image border hopefully the css support will improve and use round wrecked border for this in the future notice there is a subtle border radius css attribute that rounds the corners of this dialog each entry here is a command they have a simple two milliliter millimeter padding with light font style the last style is day it maps to the day label making chats in a specific marking chat in a specific date we use the pull border with a bluish color with that the css is done

Codename One

7. Bubble Border

Module 14: Creating a WhatsApp Clone Transcript while we are on the subject of theming there is one missing piece we neglected in the theme css the chat bubble border implements the chat bubble appearance it extends the border class and is based on the code of round rect border from codename one i won’t go into the whole code as there is a lot here in fact it’s pretty similar to the special border i created for the uber clone module so i’ll just review the changes i did for this class i added two flags to indicate whether this border has a left pointing arrow or a right pointing pointed arrow these variables are exposed using setter methods like the rest of the set of methods in this class the create shape method is where we do the actual change to implement the arrow support the arrows are drawn by moving the pen further to the side to draw the respective arrows

Codename One

8. Chat Form

Module 14: Creating a WhatsApp Clone Transcript the next step is the actual chat form the chat form is a form like the main form we discussed earlier a chat with a specific contact which is passed in the constructor as we saw in the previous main form we also have a getter for this property which we used in the main class to check if the current chat contact matches the one in the incoming message this is a common constant i use a lot to represent a single day in milliseconds it’s convenient it’s probably probably should have been static as well this is the date format used to represent the day label here this indicates whether the blue label that says today was added if not when we type in the first message to we need to add a label indicating that this message was sent today the chat form uses the y last box layout this is a special type of box layout y where the last component is pushed to the bottom of the form so here we will use that position for the text field historically i used to build apps like this with border layout and place the text field in the south both approaches are good with different trade-offs for each this approach has the downside of hiding the chat text field when scrolling up which is inconsistent with where whatsapp works so you might want to revisit this with a border layout if you want that behavior we use the chat form uiid for the background image of the form here we use a standard title with the back arrow to navigate to the previous form these are all the standard comment commands that appear in the whatsapp application i didn’t implement them and just added them to create a similar design the input container is this we just add it to the box layout y since it’s in the last mode it will glue itself to the bottom as long as it’s the last component from now on we’ll need to add all components before that component in the container now we go over the existing chats so the ui opens with the content of previous chats stored on the phone each chat has a time time is represented in milliseconds since epoch which uh is january 1st 2009 sorry 1970. we use that to divide the time by constant the constant we have for day this will give us a number that represents a day since 1970. we can then check if the time from one chat is from the same day or from a different day this can be tested with a simple not equals test notice i could have used code based on java util calendar to do this test but i think this approach is both faster and simpler in both cases we use add date to add this label before we add the chat content for a specific day we then add a message to the ui normally when we add a component to the ui we need to animate or revalidate the ui so it will show the component however since this code is running before the form is shown we don’t want such an animation as it might collide with the transition the show listener is invoked when a form is actually shown here we can do things that will happen only after the form becomes visible notice i used an anonymous inner class instead of a lambda expression here this is the reason we can remove the show listener using this command if it’s an anonymous inner class but we can’t remove it if it’s a lambda as this will map to the chat form instance this is why we need this listener in the first place this scrolls down to the last component it’s important to do this after the form is shown because if it’s done before some components could still be laid out incorrectly the add day method adds the day label if necessary there are some nuances to this beyond the label alone first we need to check if today is the current day since every day has a number associated with it as we discussed before this is pretty easy if the day is today then we need to add that special case label we also need to flip the flag indicating that it was added this boolean flag is a special case that we will discuss later there is another slightly simpler special case for yesterday showing the previous day with a special matching label otherwise we use the formatter we declared at the top of the class to generate the text of the day label we create a label with the right style and add it before the text input component which brings us to the input container i mentioned before this method creates that container which includes everything in this line including the microphone button the container starts with a text field where the messages can be typed there are two important features we need in this text field first we don’t want a border we’ll set the border to the parent container which we defined as a pill border in the css second we want this to be a multi-line text field this allows us to type in longer messages and review them however it means that enter won’t map to sending the done listener is the first way to send a message it can be triggered by using the device virtual keyboard when pressing done this adds the message to the ui and it does that with an animation that lays out the message on the form after adding the message we want to clear the text so we stop the editing process and set the text to an empty string this would have worked had we not stopped the edit wouldn’t have worked had we not stopped the editing these are the three buttons we see next to the text field here the text field is between them and not under them it just has no border the round pill border is a container that surrounds the buttons and the text field i’ll talk about attachments soon this isn’t fully implemented but i’ll cover this when we reach these methods the input container wraps these three buttons and the text field we give it the chat text field uiid which includes the perl border finally microphone has the record button design there is a partial partial worker for voice recording when we override pointer pressed we can do use the media recorder to start voice recording and stop stop it in pointer released i eventually didn’t get around to doing that if there is text in the input field the microphone icon becomes a send icon here we use the data change listener to track that and update the icon on the fly the action listener is only applicable when the microsoft microphone is in send mode it’s used to send the text in the text field this code is effectively identical to the code we saw earlier in the method it might make sense to generalize this block finally this method returns a border layout that pairs together the input container and the microphone as a single container this is a utility method i use quite often to write a number as two digits it’s useful for formatting hours so a number like 1 will be written as 0 1 and etc the logic is trivial if a number is smaller than 10 return it with a 0 prepended to it otherwise return the number as a string i make use of this method in the time formatting method below this method formats the time as hours and minutes used to display the hour next to the message this method just gets the hour and minutes from the calendar class and formats them as two digits with a colon in the middle we saw the add message method invoked when the user types a new message it’s pretty simple as most of the logic in this method is delegated to the following add message to ui no animation method but it does contain a couple of interesting bits this is why we have the today added flag if this flag isn’t set we need to add today to the dates before adding a new message this method does the heavy lifting of adding a message to the ui here we animate the addition notice i used an and weight variant of the method it’s so the scroll component to visible below will work this won’t work during the animation as the position wouldn’t be correct at that point this is the method that actually adds chat bubbles to the ui this is the logic to determine if the bubble goes in the right or left i use this logic so it will work even with groups i could have simplified it if there were only two options the main difference between the left and right chat bubble is the ui id as i mentioned in the theme the actual component placed in the chat is created by a separate method if this is a media component we’ll call create media message and if it’s a text message we use create text message the rest of this method styles the result of that method the component uses the chat bubble however we need to know whether the component should have an arrow or not notice that if we have two chat bubbles one on top the other and and the other from the same sender the second bubble doesn’t have an arrow this is true for both sides of the conversation however if we have a message from someone else then the arrow returns the this block tries to implement that logic by detecting this situation the first condition is meant to detect a chat with no components in it in this case the arrow must be shown so we can easily set the arrow on the correct side by using the left boolean variable to determine that otherwise we need to dig through the components we already added the last component is the input component so we need to look at the components before that to align chat bubbles correctly we use container wrapped wrapper so the previous container is a container we exact the child the first child of that container and save it into cnt cnt is now the previous component if the ui id of the previous component matches our current ui id it means that the previous component pinpointed to the same side pointed to the same side that means we don’t need an arrow if the uids aren’t identical the arrow needs to point into one of these directions this is another special case when the arrow is removed we also want less space between the chat bubbles this is a small nuance of the app that helps associate uh the components as part of the same conversation we wrap the component in a flow layout so it will align correctly to the left or right side we set the ui id to the ui id we picked at the beginning of the method we add the component to the offset just before the input component we stole the message itself we store the message itself as a client property in the component this makes it easier to implement features such as search as we can easily determine the business object related to a specific component finally we set the border to the component and return the container instance this version of the method does all of that but also sends the message to the server this is the version of the method we invoke when a user types a message this is the method that creates the components for a text message as you recall we have two methods one for text and one for images we use a text area to represent the text it’s more direct than span label which is technically just a text area wrapped in a container act as label removes some optimizations from the text area so the text is laid out accurately it can make a it’s slightly slower to render though we block editing and focus so a user can’t interact with the text area we set the ui id to chat text so it will use the right font and colors time is the label with the current time for this message it uses the chat time style time is the label with the current time for this message it uses the chat time style notice that short messages place the time next to the text whereas long messages place it below i chose to use the 30 character mark to decide this a better strategy might have been to calculate preferred size in some way and decide based on that but i wanted to keep things simple so i chose this approach finally we returned the bubble container that includes the text and the time the media message is similar but it uses the media file url right now the method is designed only to work with images but this can probably be fixed relatively easily we open a fast stream for the media we calculate a desired size for the media which is half the size of the portrait screen we load the image then scale it into a button as the icon of that button once there we enclose it in a layered layout so the time is overlaid at the bottom right of the layered layout as you might recall the open camera method was mapped as a listener to this button it’s a simple method that invokes capture and then adds the result as a message the last method in the class is open file which is effectively identical it uses the file chooser cn1 lib api and maps to the attach button it allows opening all files but in order for this to work we need to process all file types however i only implemented image support as i did in the previous method

Codename One

9. The New Message Form

Module 14: Creating a WhatsApp Clone Transcript the final part discussing the client-side code covers the new message form class New Message Form new message form is a form we see when we press the floating action button in the main form the class is trivial by comparison to previous the previous class it’s just a box layout y form that lets us pick a contact we wish to chat with the new group and contact buttons aren’t currently mapped to anything they’re just simple buttons List of Contacts we use the fetch contacts method to fetch the list of contacts to show here for every contact in the list of contacts we create a multi button matching the name and icon Contact Check if a contact is clicked we check if he has an id if not this is someone that might not be in the app yet so we need to contact the server and check the find registered user finds the specific user based on his phone number if we get null as a result it means this is no such registered user in the app we go back to the previous form and show a toast bar message there if there is we update the user id and save we can then launch the chat form with this new contact Launch Chat Form since the multi buttons are added asynchronously we need to revalidate so they will show on the form as i said this is a super simple short class and with that we finished the client side work

Codename One