B4J Tutorial [ABMaterial] New component ABMChat (2.50)

ABMChat is a new cool looking ABMaterial component to create a Web based chat program. The inner workings are very much like Erels ChatRoom, but with a slick interface. This can be a useful control if for example you want to give chat-like support within you own app.

Some features:
- Balloon/Bubble-like chat
- Support for some ASCII emoji
- IsTyping ballon

Video:

Code ChatShared:

B4X:
Sub Process_Globals
   Public AvoidDuplicates As Map
   Private connections As Map
   Public LastMessages As List
   Private IsTypingMap As Map
End Sub

public Sub Init
   AvoidDuplicates = Main.srvr.CreateThreadSafeMap
   connections.Initialize
   LastMessages.Initialize
   IsTypingMap.Initialize
End Sub

public Sub NewConnection(page As ChatPage, pageID As String)
   DateTime.TimeFormat = "HH:mm"
  
   Dim IdentifyBubble As ABMChatBubble
   IdentifyBubble.Initialize("Server", page.ChatName & " has joined the chat...", "Server " & DateTime.Time(DateTime.Now), "server", "server")
   JoinLeftMessage(pageID, IdentifyBubble)
   connections.Put(pageID, page)
   CallSubDelayed2(page, "CurrentConversation", LastMessages)
End Sub

public Sub NewMessage(pageID As String, Message As ABMChatBubble)
   LastMessages.Add(Message)
   For Each page As ChatPage In connections.Values
     CallSubDelayed2(page, "NewMessage", Message)
   Next
End Sub

public Sub JoinLeftMessage(pageID As String, Message As ABMChatBubble)
   For Each page As ChatPage In connections.Values
     CallSubDelayed2(page, "NewMessage", Message)
   Next
End Sub

public Sub IsTyping(pageID As String, Value As String)
   Dim typeBool As Boolean
   If Value = "" Then
     IsTypingMap.Remove(pageID.ToLowerCase)
   Else
     IsTypingMap.put(pageID.ToLowerCase, "true")
   End If
   If IsTypingMap.Size > 0 Then
     typeBool = True
   End If
   For Each page As ChatPage In connections.Values    
     CallSubDelayed3(page, "IsTyping", pageID, typeBool)
   Next
End Sub

public Sub Disconnected(page As ChatPage, pageID As String)
   If connections.ContainsKey(pageID) = False Or connections.Get(pageID) <> page Then Return
   Dim LeaveBubble As ABMChatBubble
   LeaveBubble.Initialize("Server", page.ChatName & " has left the chat...", "Server " & DateTime.Time(DateTime.Now), "server","server")
   JoinLeftMessage(pageID, LeaveBubble)
   connections.Remove(pageID)
   AvoidDuplicates.Remove(pageID.ToLowerCase)
End Sub

Public Sub HasIdentified(pageID As String) As Boolean
   Return connections.ContainsKey(pageID)
End Sub

Relevant Code ChatPage:
B4X:
Private Sub WebSocket_Disconnected
   Log("Disconnected")  
   If ABMPageId <> "" Then CallSubDelayed3(ChatShared, "Disconnected", Me, ABMPageId)
End Sub

public Sub BuildTheme()
   ' start with the base theme defined in ABMShared
   theme.Initialize("pagetheme")
   theme.AddABMTheme(ABMShared.MyTheme)
  
   ' add additional themes specific for this page
   theme.AddChatTheme("myChat")
   theme.Chat("myChat").AddBubble("server")
   theme.Chat("myChat").Bubble("server").Color = ABM.COLOR_BLACK
   theme.Chat("myChat").Bubble("server").TextColor = ABM.COLOR_WHITE
  
   theme.Chat("myChat").AddBubble("me")
   theme.Chat("myChat").Bubble("me").Color = ABM.COLOR_LIGHTBLUE
   theme.Chat("myChat").Bubble("me").TextColor = ABM.COLOR_WHITE
  
   theme.Chat("myChat").AddBubble("them")
   theme.Chat("myChat").Bubble("them").Color = ABM.COLOR_GREY
   theme.Chat("myChat").Bubble("them").ColorIntensity = ABM.INTENSITY_LIGHTEN2
   theme.Chat("myChat").Bubble("them").TextColor = ABM.COLOR_BLACK
End Sub

public Sub ConnectPage()
'   connecting the navigation bar    
  
'   init all your own variables (like a List, Map) and add your components
   Dim chat As ABMChat
   chat.Initialize(page, "conversation",600, 450, 255, "mychat")
   chat.AddBubble("Server", "I'm Server, what is your name?", "The Server", "server", "server")
    
   page.Cell(1,1).AddComponent(chat)
    
   Dim ChatInput As ABMInput
   ChatInput.Initialize(page, "ChatInput", ABM.INPUT_TEXT, "", False, "")
   ChatInput.PlaceHolderText = "Type your message here...."
   ChatInput.RaiseChangedEvent = True
   page.Cell(2,1).AddComponent(ChatInput)
  
   ' refresh the page
   page.Refresh
   ' Tell the browser we finished loading
   page.FinishedLoading
   ' restoring the navigation bar position
   page.RestoreNavigationBarPosition  
End Sub

Sub ChatInput_Changed(value As String)
   If ChatShared.HasIdentified(ABMPageId) Then
     CallSubDelayed3(ChatShared, "IsTyping", ABMPageId, value)  
   End If
End Sub

Sub ChatInput_EnterPressed(value As String)
   DateTime.TimeFormat = "HH:mm"
  
   If ChatShared.HasIdentified(ABMPageId) Then
     Dim bubble As ABMChatBubble
     bubble.Initialize(ChatName, value, ChatName & " " & DateTime.Time(DateTime.Now), "me", "them")
     CallSubDelayed3(ChatShared, "NewMessage", ABMPageId, bubble)
     CallSubDelayed3(ChatShared, "IsTyping", ABMPageId, "")  
   Else
     If value = "" Then Return
     If ChatShared.AvoidDuplicates.ContainsKey(value.ToLowerCase) Then
       Dim chat As ABMChat = page.Component("conversation")
       chat.AddBubble("Server", "Sorry, but " & value & " is already taken!", "The Server", "server", "server")
       chat.Refresh
     Else  
       ChatName = value
       ChatShared.AvoidDuplicates.Put(value.ToLowerCase, value)
       Dim chat As ABMChat = page.Component("conversation")
       chat.SetMyFrom(ChatName)
       chat.AddBubble("Server", "Welcome to ABMChat " & ChatName & "!", "The Server", "server", "server")
       chat.Refresh
       CallSubDelayed3(ChatShared, "NewConnection", Me, ABMPageId)
     End If
   End If
  
   Dim ChatInput As ABMInput = page.Component("ChatInput")
   ChatInput.Text = ""
   ChatInput.Refresh  
End Sub

public Sub NewMessage(bubble As ABMChatBubble)
   Dim chat As ABMChat = page.Component("conversation")
   chat.AddBubble2(bubble)
   chat.Refresh
   chat.ScrollToBottom   ' scroll to the end of the chat
End Sub

public Sub IsTyping(pageID As String, typeBool As Boolean)
   Dim chat As ABMChat = page.Component("conversation")
   If pageID <> ABMPageId Then
     If typeBool = False Then
       chat.ThemAreTyping(False, "") 'hide the 'is typing' bubble
     Else
       chat.ThemAreTyping(True, "") ' show the 'is typing' bubble if not yet shown  
     End If
     chat.Refresh
     chat.ScrollToBottom   ' scroll to the end of the chat  
   End If
End Sub

public Sub CurrentConversation(LastMessages As List)
   If LastMessages.Size > 0 Then
     Dim chat As ABMChat = page.Component("conversation")
     chat.SetConversation(LastMessages)
     chat.Refresh
     chat.ScrollToBottom   ' scroll to the end of the chat
   End If
End Sub

Alain
 
Last edited:

Harris

Expert
Licensed User
Longtime User
Perhaps with this structure, I could push updates ( like someone added a new note ) - so others see this without having to refresh their browser?
Thanks
 

miker2069

Active Member
Licensed User
Longtime User
Very cool! Forgive the naive question but I assume this is websockets based? I'm asking because I'm wondering if this would work behind most corporate firewalls if I set the port to 80
 

MichalK73

Well-Known Member
Licensed User
Longtime User
I think it will work for a corporate firewall on port 80, unless your administrator locks your IP server chat.
 

miker2069

Active Member
Licensed User
Longtime User
Thank You - I'll have to test it using port 80, the sample chat web site that's using 51042 port is definitely blocked by the corp. firewall at my client. I'll have to set up a VPS because they'll also block home ISP networks as well. I think if I set it to port 80 or 443 (and use SSL) it should work.
 

mindful

Active Member
Licensed User
Not quite, I started a new thread here with my initial results.
If your corporate firewall also filters traffic then it will only work with https. VPN works the same... it will work because the corporate firewall can't analyse traffic with ssl because the traffic is encrypted...
So if you setup your b4j server correcty with ssl it will work over https (443) ...
 

PCastagnetti

Member
Licensed User
Longtime User
I encountered a small issue related to removal of values from the map AvoidDuplicates

I enclose my solution to the issue:

in ChatShared
B4X:
public Sub Disconnected(page As ChatPage, pageID As String)
    If connections.ContainsKey(pageID) = False Or connections.Get(pageID) <> page Then Return
    Dim LeaveBubble As ABMChatBubble
    LeaveBubble.Initialize("Server", page.ChatName & " has left the chat...", "Server " & DateTime.Time(DateTime.Now), "server","server")
    JoinLeftMessage(pageID, LeaveBubble)
    connections.Remove(pageID)
    'AvoidDuplicates.Remove(pageID.ToLowerCase) ---> remove this line
End Sub


In ChatPage
B4X:
Private Sub WebSocket_Disconnected
    Log("Disconnected")   
    If ABMPageId <> "" Then
        CallSubDelayed3(ChatShared, "Disconnected", Me, ABMPageId)
        ChatShared.AvoidDuplicates.Remove(ChatName.ToLowerCase)
    End If
End Sub

I hope can be useful
 
Top