mirror of
https://gitlab.com/freepascal.org/fpc/pas2js.git
synced 2025-04-28 06:13:36 +02:00
253 lines
6.3 KiB
ObjectPascal
253 lines
6.3 KiB
ObjectPascal
program demowebsocket;
|
|
|
|
{$mode objfpc}
|
|
{$modeswitch externalclass}
|
|
|
|
uses
|
|
browserconsole, browserapp, JS, Classes, SysUtils, Web, strutils;
|
|
|
|
|
|
|
|
type
|
|
TServerConfig = Class External name 'Object' (TJSObject)
|
|
url : string;
|
|
end;
|
|
|
|
Var
|
|
ServerConfig : TServerConfig; external name 'serverConfig';
|
|
|
|
|
|
Type
|
|
{ TMyApplication }
|
|
TMsgKind = (mkIncoming,mkOutgoing,mkSystem);
|
|
|
|
TMyApplication = class(TBrowserApplication)
|
|
btnSend: TJSHTMLButtonElement;
|
|
EdtSender : TJSHTMLInputElement;
|
|
EdtMessage : TJSHTMLInputElement;
|
|
EdtRecipient : TJSHTMLInputElement;
|
|
divMessages : TJSHTMLDivElement;
|
|
btnConnect : TJSHTMLButtonElement;
|
|
WS : TJSWebSocket;
|
|
procedure doRun; override;
|
|
private
|
|
function AppendIcon(aParent: TJSHTMLElement; aName: String): TJSHTMLElement;
|
|
function CreateMessageEl(aKind : TMsgKind): TJSHTMLElement;
|
|
procedure DisplayClose;
|
|
procedure DisplayOpen;
|
|
function DoClosed(Event: TEventListenerEvent): boolean;
|
|
procedure doConnect;
|
|
function DoIncomingMessage(Event: TEventListenerEvent): boolean;
|
|
procedure DisplayMessage(Sender, Msg: String; Incoming: Boolean=True);
|
|
function DoOpen(Event: TEventListenerEvent): boolean;
|
|
function DoReconnect(aEvent: TJSMouseEvent): boolean;
|
|
function DoSendClick(aEvent: TJSMouseEvent): boolean;
|
|
function DoToggleConnectClick(aEvent: TJSMouseEvent): boolean;
|
|
procedure SendMessage(const aRecipient, aMessage: String);
|
|
end;
|
|
|
|
|
|
|
|
procedure TMyApplication.doRun;
|
|
|
|
begin
|
|
edtRecipient:=TJSHTMLInputElement(GetHTMLElement('edtRecipient'));
|
|
edtSender:=TJSHTMLInputElement(GetHTMLElement('edtSender'));
|
|
edtMessage:=TJSHTMLInputElement(GetHTMLElement('edtMessage'));
|
|
btnConnect:=TJSHTMLButtonElement(GetHTMLElement('btnConnect'));
|
|
btnConnect.onclick:=@DoToggleConnectClick;
|
|
btnSend:=TJSHTMLButtonElement(GetHTMLElement('btnSend'));
|
|
btnSend.onclick:=@DoSendClick;
|
|
divMessages:=TJSHTMLDivElement(GetHTMLElement('messages'));
|
|
DoConnect;
|
|
Terminate;
|
|
end;
|
|
|
|
procedure TMyApplication.doConnect;
|
|
|
|
Var
|
|
URL,aHost : string;
|
|
|
|
begin
|
|
URL:='';
|
|
if Assigned(ServerConfig) and isString(serverConfig.URL) then
|
|
URL:=serverConfig.URL;
|
|
if URL='' then
|
|
begin
|
|
aHost:=window.location.host;
|
|
aHost:=ExtractWord(1,aHost,[':']);
|
|
URL:='ws://'+aHost+':8080/';
|
|
end;
|
|
try
|
|
WS:=TJSWebsocket.New(url);
|
|
WS.onmessage:=@DoIncomingMessage;
|
|
WS.onclose:=@DoClosed;
|
|
WS.onopen:=@DoOpen;
|
|
except
|
|
on TJSError do
|
|
Window.Alert('Could not connect to websocket server at '+URL);
|
|
end;
|
|
end;
|
|
|
|
function TMyApplication.DoOpen(Event: TEventListenerEvent): boolean;
|
|
begin
|
|
btnSend.disabled:=False;
|
|
DisplayOpen;
|
|
btnConnect.InnerText:='Disconnect';
|
|
end;
|
|
|
|
function TMyApplication.DoClosed(Event: TEventListenerEvent): boolean;
|
|
begin
|
|
btnSend.disabled:=true;
|
|
btnConnect.InnerText:='Connect';
|
|
DisplayClose;
|
|
end;
|
|
|
|
function TMyApplication.DoIncomingMessage(Event: TEventListenerEvent): boolean;
|
|
|
|
Var
|
|
Msg: TJSMessageEvent absolute Event;
|
|
JS : TJSObject;
|
|
|
|
begin
|
|
if isString(Msg.Data) then
|
|
begin
|
|
JS:=TJSJSON.parseObject(String(Msg.Data));
|
|
DisplayMessage(String(JS['from']),String(JS['msg']),True)
|
|
end
|
|
else
|
|
DisplayMessage('','<<unknown data arrived>>',True);
|
|
end;
|
|
|
|
function TMyApplication.CreateMessageEl(aKind : TMsgKind): TJSHTMLElement;
|
|
|
|
Var
|
|
ImgDiv,ImgEl,msgEl : TJSHTMLElement;
|
|
|
|
begin
|
|
MsgEl:=TJSHTMLElement(Document.createElement('DIV'));
|
|
if aKind=mkSystem then
|
|
begin
|
|
MsgEl.className:='text-center my-2';
|
|
end
|
|
else
|
|
begin
|
|
msgEl.className:='d-flex align-items-center'+Ifthen(aKind=mkIncoming,'',' text-right justify-content-end');
|
|
ImgDiv:=TJSHTMLElement(Document.createElement('DIV'));
|
|
ImgDiv.ClassName:='text-left pr-1';
|
|
ImgEl:=TJSHTMLElement(Document.createElement('IMG'));
|
|
ImgEl['Src']:=IfThen(aKind=mkIncoming,'guest','you')+'.png';
|
|
ImgDiv.AppendChild(ImgEl);
|
|
if aKind=mkIncoming then
|
|
msgEl.AppendChild(ImgDiv);
|
|
end;
|
|
Result:=TJSHTMLElement(Document.createElement(IfThen(aKind=mkSystem,'span','div')));
|
|
if aKind=mkSystem then
|
|
Result.className:='between'
|
|
else
|
|
Result.className:='pr-2'+IfThen(aKind=mkIncoming,' pl-1','');
|
|
msgEl.AppendChild(Result);
|
|
if aKind=mkOutgoing then
|
|
msgEl.AppendChild(ImgDiv);
|
|
divMessages.appendChild(msgEl);
|
|
msgEl.scrollIntoView;
|
|
end;
|
|
|
|
function TMyApplication.AppendIcon(aParent: TJSHTMLElement; aName: String
|
|
): TJSHTMLElement;
|
|
|
|
begin
|
|
Result:=TJSHTMLElement(Document.createElement('i'));
|
|
Result.className:='fas fa-'+aName+' mr-3';
|
|
aParent.AppendChild(Result);
|
|
end;
|
|
|
|
procedure TMyApplication.DisplayClose;
|
|
|
|
Var
|
|
iEl,pEl : TJSHTMLElement;
|
|
|
|
begin
|
|
Pel:=CreateMessageEl(mkSystem);
|
|
iEl:=AppendIcon(Pel,'plug');
|
|
iEl.onclick:=@DoReconnect;
|
|
pEl.AppendChild(Document.createTextNode('Connection closed, click icon to reconnect'));
|
|
end;
|
|
|
|
procedure TMyApplication.DisplayOpen;
|
|
|
|
Var
|
|
pEl : TJSHTMLElement;
|
|
|
|
begin
|
|
Pel:=CreateMessageEl(mkSystem);
|
|
AppendIcon(Pel,'link');
|
|
pEl.AppendChild(Document.createTextNode('Connection open, you can start messaging'));
|
|
end;
|
|
|
|
|
|
|
|
procedure TMyApplication.DisplayMessage(Sender,Msg: String; Incoming: Boolean = True);
|
|
|
|
Const
|
|
kinds : Array[Boolean] of TMsgKind = (mkOutgoing,mkIncoming);
|
|
|
|
Var
|
|
pEl,pEl2 : TJSHTMLElement;
|
|
|
|
begin
|
|
pEl:=CreateMessageEl(Kinds[Incoming]);
|
|
if (Sender<>'') then
|
|
begin
|
|
pEl2:=TJSHTMLElement(Document.createElement('span'));
|
|
pEl2.className:='name';
|
|
pEl2.innerText:=Sender;
|
|
pEl.appendChild(pEl2);
|
|
end;
|
|
pEl2:=TJSHTMLElement(Document.createElement('p'));
|
|
PEL2.className:='msg';
|
|
PEL2.AppendChild(Document.createTextNode(Msg));
|
|
pEl.AppendChild(pEL2);
|
|
end;
|
|
|
|
function TMyApplication.DoReconnect(aEvent: TJSMouseEvent): boolean;
|
|
begin
|
|
DoConnect;
|
|
end;
|
|
|
|
procedure TMyApplication.SendMessage(const aRecipient,aMessage: String);
|
|
|
|
Var
|
|
JS : TJSObject;
|
|
|
|
begin
|
|
JS:=New(['from',EdtSender.Value,'msg',aMessage,'to',aRecipient]);
|
|
WS.send(TJSJSON.Stringify(JS));
|
|
DisplayMessage('you',aMessage,False);
|
|
end;
|
|
|
|
function TMyApplication.DoSendClick(aEvent: TJSMouseEvent): boolean;
|
|
begin
|
|
SendMessage(EDTRecipient.Value, EdtMessage.Value);
|
|
end;
|
|
|
|
function TMyApplication.DoToggleConnectClick(aEvent: TJSMouseEvent): boolean;
|
|
begin
|
|
if btnConnect.InnerText='Connect' then
|
|
doConnect
|
|
else
|
|
begin
|
|
WS.close;
|
|
WS:=nil;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
Application : TMyApplication;
|
|
|
|
begin
|
|
Application:=TMyApplication.Create(nil);
|
|
Application.Initialize;
|
|
Application.Run;
|
|
end.
|