Fork us on GitHub

RAD Chat Room - Part 5

Changes in media, text input and iOS rendering
RAD Chat Room - Part 5

RAD Chat Room - Part 5

This is part 5 of the RAD Chatroom tutorial. You can find part 1 here, part 2 here, part 3 here and part 4 here.

Adding A Photo Capture Feature

Most messaging applications include the ability to add photos to messages. Let’s add this feature to our chat app now.

First we’ll define a new action called "capturePhoto", and add to the the TEXT_ACTIONS category of our view node.

public static final ActionNode capturePhoto = action(
        icon(FontImage.MATERIAL_CAMERA)
);

...

ViewNode viewNode = new ViewNode(
    actions(ChatRoomView.SEND_ACTION, send),
    actions(ProfileAvatarView.PROFILE_AVATAR_CLICKED_MENU, phone, videoConference),
    actions(ChatBubbleView.CHAT_BUBBLE_LONG_PRESS_MENU, likeAction),
    actions(ChatBubbleView.CHAT_BUBBLE_BADGES, likedBadge),
    actions(ChatRoomView.TEXT_ACTIONS, capturePhoto) (1)
);
1 Added capturePhoto action to the TEXT_ACTIONS category so that it will appear as a button beside the text field.

And we’ll also add a handler for this action, which will capture a photo, and emed the photo in a message that we will add to the chat room’s view model.

addActionListener(capturePhoto, evt->{
    evt.consume();
    String photoPath = Capture.capturePhoto();
    if (photoPath == null) {
        // User canceled the photo capture
        return;
    }

    File photos = new File("photos"); (1)
    photos.mkdirs();
    Entity entity = evt.getEntity();
    File photo = new File(photos, System.currentTimeMillis()+".png");
    try (InputStream input = FileSystemStorage.getInstance().openInputStream(photoPath);
            OutputStream output = FileSystemStorage.getInstance().openOutputStream(photo.getAbsolutePath())) {
        Util.copy(input, output);

        ChatBubbleView.ViewModel message = new ChatBubbleView.ViewModel();
        message.attachmentImageUrl(photo.getAbsolutePath()); (2)
        message.isOwn(true);
        message.date(new Date());
        EntityList messages = entity.getEntityList(ChatRoom.messages); (3)
        if (messages == null) {
            throw new IllegalStateException("This chat room has no messages list set up");
        }
        messages.add(message); (4)

    } catch (IOException ex) {
        Log.e(ex);
        ToastBar.showErrorMessage(ex.getMessage());
    }
});
1 We will create a directory named "photos" where we store all of the photos for the app.
2 Set the path of this photo under attachmentImageUrl. The ChatBubbleView will accept http, https, and file URLs, as well as storage keys. It will render them correctly in the view according to the type of URL it is.
3 The "entity" of this event is the view model for the ChatRoomView. Here we use the ChatRoom.messages tag to access the messages list in a loosely coupled way. This code will work even if we change the class that we use for the ChatRoomView’s view model.
4 Adding the message to the messages entity list will trigger a list change event and it will be rendered automatically in the chat room.

Now, let’s fire the chat up again and take it for a test drive.

The capturePhoto action is rendered as a button beside the input text field
Figure 1. The capturePhoto action is rendered as a button beside the input text field

You should now be able to click on the "capture photo" button to capture an image. In the simulator, it will open a file dialog to select an image. On device, it will activate the devices camera so that you can take a photo. After capturing an image, it should be added to the chat inside a message bubble as shown below:

Photo appears in chat after capture
Figure 2. Photo appears in chat after capture

Linking to a Back-end Chat Server

In this tutorial we created a mock chat application in order to demostrate the ChatRoomView, which is a user interface component. It did not include any integration with a server so it doesn’t allow you to actually chat with other people. Linking to a server is not difficult, and the MVC architecture of this example should make it very clear how the integration should occur. I’ll leave this integration as an exercise for the reader. As a starting point, I recommend checking out the cn1-websockets library, and its chat demo.

Share this Post:

Posted by Steve Hannah

Steve writes software for Codename One. He is an open source enthusiast who loves to tinker with new technologies.