-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathclient.coffee
executable file
·268 lines (237 loc) · 6.89 KB
/
client.coffee
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
Db = require 'db'
Dom = require 'dom'
Chat = require 'chat'
Event = require 'event'
Form = require 'form'
Obs = require 'obs'
Page = require 'page'
Photo = require 'photo'
Plugin = require 'plugin'
Server = require 'server'
Time = require 'time'
Ui = require 'ui'
{tr} = require 'i18n'
myUserId = Plugin.userId()
if Plugin.groupId() < 0
contactUserId = 3-myUserId
exports.render = !->
Dom.style
fontSize: '90%'
Chat.renderMessages
newCount: Obs.peek -> Event.getUnread() || 0
content: messageContent = (msg, num) !->
return if !msg.isHash()
byUserId = msg.get('by')
name = Plugin.userName byUserId
type = msg.get('type')
if type in [10,11,12]
Dom.div !->
Dom.cls 'chat-system'
Dom.div !->
Dom.cls 'chat-content'
if byUserId is myUserId
name = tr("You")
Dom.text if type is 10
tr("%1 created the happening", name)
else if type is 11
tr("%1 joined", name)
else
tr("%1 left", name)
Dom.onTap !->
Plugin.userInfo(byUserId)
return
# normal message
Dom.div !->
Dom.cls 'chat-msg'
if byUserId is myUserId
Dom.cls 'chat-me'
Ui.avatar Plugin.userAvatar(byUserId),
style: margin: '0 3px'
onTap: !-> Plugin.userInfo(byUserId)
Dom.div !->
Dom.cls 'chat-content'
if (photoUpload = msg.get("photoUpload"))
Dom.div !->
Dom.style
background: "url(#{msg.get('thumb')}) 50% 50% no-repeat"
backgroundSize: 'cover'
width: "90px"
height: "70px"
padding: "40px 0 0 60px"
Ui.spinner 30
else if (photoKey = msg.get('photo'))
Dom.div !->
Dom.cls 'img'
Dom.style
width: '150px' #
height: '150px' #
margin: '2px 0' # these are also in main css, but that might not have updated yet.. (wait for major update to remove these)
backgroundImage: "url("+Photo.url(photoKey, 400)+")"
backgroundSize: 'cover'
backgroundPosition: '50% 50%'
Dom.onTap !->
Page.nav !->
renderPhoto msg, num
else if photoKey is ''
Dom.div !->
Dom.cls 'chat-nophoto'
Dom.text tr("Photo")
Dom.br()
Dom.text tr("removed")
text = msg.get('text')
Dom.userText text if text
Dom.div !->
Dom.cls 'chat-info'
Dom.text name
Dom.text " • "
if time = msg.get('time')
Time.deltaText time, 'short'
else
Dom.text tr("sending")
Ui.dots()
if !photoUpload
Dom.onTap !->
msgModal msg, num
Obs.observe !->
Photo.uploads.iterate (newPhoto) !-> # Previews of image uploads
Page.scroll 'down', true # Scroll to the preview of the image that is getting uploaded
preview = Obs.create newPhoto.get()
preview.set "photoUpload", true
preview.set "by", Plugin.userId()
messageContent(preview)
typingSub = Obs.create {}
Server.send 'typingSub', (delta) !-> typingSub.patch delta
Dom.div !->
wasNearBottom = Page.nearBottom()
users = (Plugin.userName(userId) for userId of typingSub.get() when +userId isnt myUserId)
Dom.style
fontSize: '80%'
padding: '4px 0'
color: '#999'
height: '16px' # reserve fixed space so redrawing does not trigger new scroll-down
display: if users.length then '' else 'none'
if len=users.length
Dom.text users.join(' & ')
Dom.text if len>1 then tr(" are typing") else tr(" is typing")
Ui.dots()
if wasNearBottom
Page.scroll 'down', true
Page.setFooter !->
Chat.renderInput
typing: true
placeholder: tr("Send a message...")
renderPhoto = (msg, num) !->
Dom.style
padding: 0
content = (identifier) !->
message = Db.shared.ref(0|identifier/100, identifier%100)
return if !message?
byUserId = message.get('by')
photoKey = message.get('photo')
return if !byUserId? or !photoKey?
Page.setTitle tr("Posted by %1", Plugin.userName(byUserId))
opts = []
if Photo.share
opts.push
label: tr("Share")
icon: 'share'
action: !-> Photo.share photoKey
if Photo.download
opts.push
label: tr("Download")
icon: 'boxdown'
action: !-> Photo.download photoKey
if byUserId is myUserId or Plugin.userIsAdmin()
opts.push
label: tr("Remove")
icon: 'trash'
action: !->
require('modal').confirm null, tr("Remove photo?"), !->
Server.sync 'removePhoto', identifier, !->
message.set('photo', '')
Page.back()
Page.setActions opts
(require 'photoview').render
current: num
getNeighbourIds: (id) ->
max = Db.shared.peek('maxId')||0
right = parseInt(id)-1
while !((rightValue = Db.shared.peek(0|right/100, right%100, "photo"))?) && right > 0
right--
left = parseInt(id)+1
while !((leftValue = Db.shared.peek(0|left/100, left%100, "photo"))?) && left <= max
left++
left = undefined if !leftValue? or leftValue.length is 0
right = undefined if !rightValue? or rightValue.length is 0
[right,left]
idToPhotoKey: (id) ->
Db.shared.get 0|id/100, id%100, 'photo'
fullHeight: true
content: content
msgModal = (msg, num) !->
time = msg.get('time')
return if !time
Modal = require('modal')
byUserId = msg.get('by')
Modal.show false, !->
Dom.div !->
Dom.style
margin: '-12px'
Ui.item !->
Ui.avatar Plugin.userAvatar(byUserId)
Dom.div !->
Dom.text tr("Sent by %1", Plugin.userName(byUserId))
Dom.div !->
Dom.style fontSize: '80%'
Dom.text (new Date(time*1000)+'').replace(/\s[\S]+\s[\S]+$/, '')
Dom.onTap !->
Plugin.userInfo byUserId
if !!Form.clipboard and clipboard = Form.clipboard()
Ui.item !->
Dom.text tr("Copy text")
Dom.onTap !->
clipboard(msg.get('text'))
require('toast').show tr("Copied to clipboard")
Modal.remove()
return if contactUserId and byUserId is contactUserId
read = Obs.create false
Server.send 'getRead', num, read.func()
Ui.item !->
if read.get() is false
Dom.div !->
Dom.style Flex: 1
Dom.text tr("Seen by")
Ui.spinner 24
else if contactUserId
if read.get(contactUserId)
Dom.text tr("Seen by %1", Plugin.userName(contactUserId))
else
Dom.text tr("Not seen by %1", Plugin.userName(contactUserId))
else
count = read.count().get()
if count >= Plugin.users.count().get()-1
Dom.text tr("Seen by all members")
else
Dom.text tr("Seen by %1 member|s", count)
Dom.onTap !->
Modal.show tr("Seen by"), !->
Dom.div !->
Dom.style
margin: '-12px'
maxHeight: '60%'
minWidth: '15em'
Dom.overflow()
read.iterate (r) !->
Ui.item !->
id = r.key()
Ui.avatar Plugin.userAvatar(id)
Dom.div Plugin.userName(id)
Dom.onTap !->
Plugin.userInfo id
, (r) -> +r.key()
, undefined, ['ok', tr("Close")]
Dom.css
'.chat-msg .chat-content.tap':
background: '#ddd !important'
'.chat-msg.chat-me .chat-content.tap':
background: '#D6DDE4 !important'