#How to live update chat screen when a new chat is entered to the ChatHistory context (Static list)

57 messages · Page 1 of 1 (latest)

rain tapir
#

In the Swing application

stable spokeBOT
#

This post has been reserved for your question.

Hey @rain tapir! Please use /close or the Close Post button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.

TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.

rain tapir
#

There are two Actors Customer and Emplyee

Employee gets a UI to chat and also the customer

#

This is how the chats are managed across the application

public class ChatHistory {

    private static Map<Actor, List<Chat>> chats = new HashMap<>();

    public static Map<Actor, List<Chat>> getChats() {
        return chats;
    }

    public static List<Chat> getChatsByActor(Actor actor) {
        if (chats != null) {
            return chats.get(actor);
        }else{
            return new LinkedList<>();
        }
    }

    public static void addChat(Actor from,Actor to, String message) {

        if (chats != null) {
            if (chats.get(from) != null) {
                List<Chat> messages = chats.get(from);
                Chat chat = new Chat(from, to, message);
                messages.add(chat);
                chats.put(from, messages);
            }
            if (chats.get(from) == null) {
                List<Chat> messages = new LinkedList<>();
                Chat chat = new Chat(from, to, message);
                messages.add(chat);
                chats.put(from, messages);
            }
        }

    }

    

}

#

To display the Chats for each Actor I use a method

which will load the chats

    private void loadChat() {
        chatScrollPane.removeAll();
        rowCount = 0;

        Map<Actor, List<Chat>> chats = ChatHistory.getChats();

        for (Map.Entry<Actor, List<Chat>> entry : chats.entrySet()) {
            Actor key = entry.getKey();
            List<Chat> value = entry.getValue();

//            if (ChatActorUtil.getName(key).equals(this.customer.getName())) {
            if (key instanceof ChatCustomer) {
                value.forEach(e -> {
                    if (e.getSender() instanceof ChatCustomer) {
                        ChatCustomer customer = (ChatCustomer) key;

                        if (customer.getName().equals(this.customer.getName())) {
                            chatScrollPane.add(new ToChatPanel(e.getMessage()));
                            rowCount++;
                        }
                    }

                });
            }

            if (key instanceof ChatEmployee) {

                ChatEmployee employee = (ChatEmployee) key;

                value.forEach(e -> {
                    ChatCustomer customer = (ChatCustomer) e.getReceive();

                    if (customer.getName().equals(this.customer.getName())) {
                        chatScrollPane.add(new FromChatPanel("Employee", e.getMessage()));
                        rowCount++;
                    }
                });
            }

        }
        chatScrollPane.setLayout(new GridLayout(rowCount, 1));
        chatScrollPane.revalidate();
        chatScrollPane.repaint();
    }
#

but the problem is this won't live update I have to manually refresh

#

or manually call the loadChats method

#

This is the mediator that manages the chats between actors


public class ConcreteMediator implements Mediator {

    private List<Actor> actors;

    public ConcreteMediator() {
        this.actors = ActorStorage.getActorList();
    }

    public void addActor(Actor actor) {
        ActorStorage.setActor(actor);
//        this.actors.add(actor);
    }

    @Override
    public void sendMessage(String message, Actor from, Actor to) {

        if (from instanceof ChatEmployee) {
            to.receiveMessage(message, from);

        }

        if (from instanceof ChatCustomer) {

            to.receiveMessage(message, from);
        }
        ChatHistory.addChat(from, to, message);
    }
}

fossil rover
#

when should what change?

#

Also, in most cases, you want to use ArrayList instead of LinkedList

rain tapir
#

like how we chat in discord

fossil rover
#

Are they on different devices?

#

Are they communicating over sockets?

rain tapir
#

no Just same instance

fossil rover
#

ah ok

rain tapir
#

One Swing application

fossil rover
#

Can you show the Chat class?

rain tapir
#

yeah

#
public class Chat {
    
    private Actor sender;
    private Actor receiver;
    private String message;

    public Chat(Actor sender, Actor receiver, String message) {
        this.sender = sender;
        this.receiver = receiver;
        this.message = message;
    }

    public Actor getSender() {
        return sender;
    }

    public void setSender(Actor sender) {
        this.sender = sender;
    }

    public Actor getReceive() {
        return receiver;
    }

    public void setReceive(Actor receive) {
        this.receiver = receive;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
    

    
}

#

This is the customer's UI after confirming the order

#

They get a Chat UI to chat

#

This is the UI what the employee get to chat with the customer

fossil rover
#

Can you show the receiveMessage method?

rain tapir
#

Concreate Mediator calls the receiveMessage method



public class ConcreteMediator implements Mediator {

    private List<Actor> actors;

    public ConcreteMediator() {
        this.actors = ActorStorage.getActorList();
    }

    public void addActor(Actor actor) {
        ActorStorage.setActor(actor);
//        this.actors.add(actor);
    }

    @Override
    public void sendMessage(String message, Actor from, Actor to) {

        if (from instanceof ChatEmployee) {
            to.receiveMessage(message, from);

        }

        if (from instanceof ChatCustomer) {

            to.receiveMessage(message, from);
        }
        ChatHistory.addChat(from, to, message);
    }
}
fossil rover
#

I meant the method itself

#

not how it's called

rain tapir
#

like inside the actors?

#

yah

public class ChatEmployee implements Actor {

    private Mediator mediator;
    private String name;

    public ChatEmployee(Mediator mediator, String name) {
        this.mediator = mediator;
        this.name = name;
        ConcreteMediator concreteMediator = (ConcreteMediator) this.mediator;
        concreteMediator.addActor(this);
    }

    public String getName() {
        return name;
    }

    @Override
    public void sendMessage(String message, Actor to) {
        mediator.sendMessage(message, this, to);
    }

    @Override
    public void receiveMessage(String message, Actor from) {

        ChatCustomer customer = (ChatCustomer)from;
        System.out.println(this.name + " receives messages " + message+ " from "+customer.getName());
    }
}

fossil rover
#

What about updating the UI there?

rain tapir
#

I didn't really nothing inside

fossil rover
#

btw can you show the Actor interface?

#

I don't think you should use instanceof

rain tapir
#
public interface Actor {
    void sendMessage(String message,Actor to);
    void receiveMessage(String message, Actor from);
}
fossil rover
#

Why the


        if (from instanceof ChatEmployee) {
            to.receiveMessage(message, from);

        }

        if (from instanceof ChatCustomer) {

            to.receiveMessage(message, from);
        }

?

#

You can just do to.receiveMessage(message, from);

rain tapir
strange haloBOT
#

What about updating the UI there?

fossil rover
#

I think the best way is to have a reference to the UI in your ChatEmployee (and ChatCustomer)

rain tapir
#

yah yah

fossil rover
#

and update it from there

rain tapir
#

but wouldn't that couple the UI?

fossil rover
#

you can use an interface

#

For example, you could create a ChatUpdater interface

#

with a method addChatMessage

#

or actually use a listener

#

that's better

#

You create an interface like that

public interface ChatListener{
  void onChatMessageReceived(Actor from, String message)
}
rain tapir
fossil rover
fossil rover
#

and in the receiveMessage, you call the onChatMessageReceived of all listeners

fossil rover
rain tapir
#

ook alright

fossil rover
#

Would that work for you?

rain tapir
#

yah I will give a try and update you