-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathChatbox.fan
136 lines (118 loc) · 3.71 KB
/
Chatbox.fan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
using afWebSockets
using afIoc
using afBedSheet
using afBedSheet::Text as BsText
using afConcurrent::Synchronized
using afDuvet::DuvetModule
using afDuvet::HtmlInjector
using concurrent::ActorPool
using fwt
using build::BuildPod
class Main {
Void main(Str[] args) {
if (args.first == "-client")
ChatboxClient().main
if (args.first == "-server")
BedSheetBuilder(AppModule#.qname).addModulesFromPod("afWebSockets").startWisp(8069)
if (args.first == "-build")
Builder().main
}
}
const class AppModule {
@Contribute { serviceType=Routes# }
Void contributeRoutes(Configuration conf) {
conf.add(Route(`/`, ChatboxRoutes#indexPage))
conf.add(Route(`/ws`, ChatboxRoutes#serviceWebSocket))
}
}
const class ChatboxRoutes {
@Inject private const WebSockets webSockets
@Inject private const HtmlInjector htmlInjector
new make(|This|in) { in(this) }
BsText indexPage() {
htmlInjector.injectFantomMethod(ChatboxClient#main)
return BsText.fromHtml(
"<!DOCTYPE html>
<html>
<head>
<title>ChatBox - A WebSocket Demo</title>
</head>
<body>
</body>
</html>")
}
WebSocket serviceWebSocket() {
WebSocket() {
ws := it
onMessage = |MsgEvent me| {
webSockets.broadcast("${ws.id} says, '${me.txt}'")
}
}
}
}
@Js
class ChatboxClient {
Void main() {
webSock := WebSocket().open(`ws://localhost:8069/ws`)
convBox := Text { text = "The conversation:\r\n"; multiLine = true; editable = false }
textBox := Text { text = "Say something!" }
sendMsg := |Event e| {
webSock.sendText(textBox.text)
textBox.text = ""
}
webSock.onMessage = |MsgEvent msgEnv| {
convBox.text += "\r\n" + msgEnv.txt
}
textBox.onAction.add(sendMsg)
window := Window {
title = "ChatBox - A WebSocket Demo"
InsetPane {
EdgePane {
center = convBox
bottom = EdgePane {
center = textBox
right = Button { text = "Send"; onAction.add(sendMsg) }
}
},
},
}
// desktop only code
if (Env.cur.runtime != "js") {
// ensure event funcs are run in the UI thread
safeFunc := Unsafe(webSock.onMessage)
webSock.onMessage = |MsgEvent msgEnv| {
safeMess := Unsafe(msgEnv)
Desktop.callAsync |->| { safeFunc.val->call(safeMess.val) }
}
// call the blocking read() method in a background thread
safeSock := Unsafe(webSock)
Synchronized(ActorPool()).async |->| {
safeSock.val->read
}
}
window.open
}
}
class Builder : BuildPod {
new make() {
podName = "wsChatbox"
summary = "A WebSocket Demo"
meta = [
"proj.name" : "ChatBox - A WebSocket Demo",
"afIoc.module" : "wsChatbox::AppModule",
]
depends = [
"sys 1.0.70 - 1.0",
"fwt 1.0.70 - 1.0",
"web 1.0.70 - 1.0",
"build 1.0.70 - 1.0",
"concurrent 1.0.70 - 1.0",
"afIoc 3.0.6 - 3.0",
"afConcurrent 1.0.20 - 1.0",
"afBedSheet 1.5.10 - 1.5",
"afDuvet 1.1.8 - 1.1",
"afWebSockets 0.2.0 - 0.1",
]
srcDirs = [`Chatbox.fan`]
}
}