Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initial implementation of external app #420

Merged
merged 3 commits into from
Aug 7, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/rocketchat-external/app/.meteor/packages
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,12 @@ underscore
jquery
random
ejson
coffeescript
arunoda:streams
kadira:flow-router
kadira:blaze-layout
konecty:nrr
less
underscorestring:underscore.string
momentjs:moment
mizzao:timesync
18 changes: 18 additions & 0 deletions packages/rocketchat-external/app/client/lib/avatar.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@getAvatarUrlFromUsername = (username) ->
key = "avatar_random_#{username}"
random = Session.keys[key] or 0
if not username?
return

return "#{Meteor.absoluteUrl()}avatar/#{username}.jpg?_dc=#{random}"

@updateAvatarOfUsername = (username) ->
key = "avatar_random_#{username}"
Session.set key, Math.round(Math.random() * 1000)

for key, room of RoomManager.openedRooms
url = getAvatarUrlFromUsername username

$(room.dom).find(".message[data-username='#{username}'] .avatar-image").css('background-image', "url(#{url})");

return true
193 changes: 193 additions & 0 deletions packages/rocketchat-external/app/client/lib/chatMessages.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
class @ChatMessages
init: (node) ->
this.editing = {}

# this.messageMaxSize = RocketChat.settings.get('Message_MaxAllowedSize')
this.wrapper = $(node).find(".wrapper")
this.input = $(node).find(".input-message").get(0)
# this.bindEvents()
return

resize: ->
dif = 60 + $(".messages-container").find("footer").outerHeight()
$(".messages-box").css
height: "calc(100% - #{dif}px)"

toPrevMessage: ->
msgs = this.wrapper.get(0).querySelectorAll(".own:not(.system)")
if msgs.length
if this.editing.element
if msgs[this.editing.index - 1]
this.edit msgs[this.editing.index - 1], this.editing.index - 1
else
this.edit msgs[msgs.length - 1], msgs.length - 1

toNextMessage: ->
if this.editing.element
msgs = this.wrapper.get(0).querySelectorAll(".own:not(.system)")
if msgs[this.editing.index + 1]
this.edit msgs[this.editing.index + 1], this.editing.index + 1
else
this.clearEditing()

getEditingIndex: (element) ->
msgs = this.wrapper.get(0).querySelectorAll(".own:not(.system)")
index = 0
for msg in msgs
if msg is element
return index
index++
return -1

edit: (element, index) ->
return if element.classList.contains("system")
this.clearEditing()
id = element.getAttribute("id")
message = ChatMessage.findOne { _id: id, 'u._id': Meteor.userId() }
this.input.value = message.msg
this.editing.element = element
this.editing.index = index or this.getEditingIndex(element)
this.editing.id = id
element.classList.add("editing")
this.input.classList.add("editing")
setTimeout =>
this.input.focus()
, 5

clearEditing: ->
if this.editing.element
this.editing.element.classList.remove("editing")
this.input.classList.remove("editing")
this.editing.id = null
this.editing.element = null
this.editing.index = null
this.input.value = this.editing.saved or ""
else
this.editing.saved = this.input.value

send: (rid, input) ->
if _.trim(input.value) isnt ''
if this.isMessageTooLong(input)
return Errors.throw t('Error_message_too_long')
# KonchatNotification.removeRoomNotification(rid)
msg = input.value
input.value = ''
msgObject = { _id: Random.id(), rid: rid, msg: msg}
# this.stopTyping(rid)
#Check if message starts with /command
if msg[0] is '/'
match = msg.match(/^\/([^\s]+)(?:\s+(.*))?$/m)
if(match?)
command = match[1]
param = match[2]
Meteor.call 'slashCommand', {cmd: command, params: param, msg: msgObject }
else
#Run to allow local encryption
#Meteor.call 'onClientBeforeSendMessage', {}
Meteor.call 'sendMessageExternal', msgObject

deleteMsg: (message) ->
Meteor.call 'deleteMessage', message, (error, result) ->
if error
return Errors.throw error.reason

update: (id, rid, input) ->
if _.trim(input.value) isnt ''
msg = input.value
Meteor.call 'updateMessage', { id: id, msg: msg }
this.clearEditing()
# this.stopTyping(rid)

startTyping: (rid, input) ->
if _.trim(input.value) isnt ''
MsgTyping.start(rid)
else
MsgTyping.stop(rid)

stopTyping: (rid) ->
MsgTyping.stop(rid)

bindEvents: ->
if this.wrapper?.length
$(".input-message").autogrow
postGrowCallback: =>
this.resize()

tryCompletion: (input) ->
value = input.value.match(/[^\s]+$/)
if value?.length > 0
value = value[0]

re = new RegExp value, 'i'

user = Meteor.users.findOne username: re
if user?
input.value = input.value.replace value, "@#{user.username} "

keyup: (rid, event) ->
input = event.currentTarget
k = event.which
keyCodes = [
13, # Enter
20, # Caps lock
16, # Shift
9, # Tab
27, # Escape Key
17, # Control Key
91, # Windows Command Key
19, # Pause Break
18, # Alt Key
93, # Right Click Point Key
45, # Insert Key
34, # Page Down
35, # Page Up
144, # Num Lock
145 # Scroll Lock
]
keyCodes.push i for i in [35..40] # Home, End, Arrow Keys
keyCodes.push i for i in [112..123] # F1 - F12

# unless k in keyCodes
# this.startTyping(rid, input)

keydown: (rid, event) ->
input = event.currentTarget
k = event.which
this.resize(input)
if k is 13 and not event.shiftKey
event.preventDefault()
event.stopPropagation()
if this.editing.id
this.update(this.editing.id, rid, input)
else
this.send(rid, input)
return

if k is 9
event.preventDefault()
event.stopPropagation()
@tryCompletion input

if k is 27
if this.editing.id
event.preventDefault()
event.stopPropagation()
this.clearEditing()
return
else if k is 38 or k is 40 # Arrow Up or down
if k is 38
return if input.value.slice(0, input.selectionStart).match(/[\n]/) isnt null
this.toPrevMessage()
else
return if input.value.slice(input.selectionEnd, input.value.length).match(/[\n]/) isnt null
this.toNextMessage()

event.preventDefault()
event.stopPropagation()

# ctrl (command) + shift + k -> clear room messages
else if k is 75 and ((navigator?.platform?.indexOf('Mac') isnt -1 and event.metaKey and event.shiftKey) or (navigator?.platform?.indexOf('Mac') is -1 and event.ctrlKey and event.shiftKey))
RoomHistoryManager.clear rid

isMessageTooLong: (input) ->
input?.value.length > this.messageMaxSize
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@ChatMessage = new Meteor.Collection null
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// This will add underscore.string methods to Underscore.js
// except for include, contains, reverse and join that are
// dropped because they collide with the functions already
// defined by Underscore.js.
_.mixin(s.exports())
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Meteor.methods
sendMessageExternal: (message) ->
# if not Meteor.userId()
# throw new Meteor.Error 203, t('User_logged_out')

if _.trim(message.msg) isnt ''

message.ts = new Date(Date.now() + TimeSync.serverOffset())

message.u =
# _id: Meteor.userId()
username: 'visitor'

message.temp = true

# message = RocketChat.callbacks.run 'beforeSaveMessage', message

ChatMessage.insert message
5 changes: 5 additions & 0 deletions packages/rocketchat-external/app/client/routes/router.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FlowRouter.route '/',
name: 'index'

action: ->
BlazeLayout.render 'main', {center: 'room'}
32 changes: 32 additions & 0 deletions packages/rocketchat-external/app/client/stylesheets/main.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
body {
padding: 0;
margin: 0;
}
.external-room {
position: fixed;
top: 0;
bottom: 0;
background-color: blue;
.title {
background-color: green;
position: fixed;
top: 0;
width: 100%;
height: 60px;
}
.wrapper {
background-color: purple;
top: 60px;
bottom: 60px;
position: fixed;
width: 100%;
overflow-y: auto;
}
.footer {
background-color: red;
position: fixed;
bottom: 0;
width: 100%;
height: 60px;
}
}
3 changes: 0 additions & 3 deletions packages/rocketchat-external/app/client/test.html

This file was deleted.

12 changes: 0 additions & 12 deletions packages/rocketchat-external/app/client/test.js

This file was deleted.

14 changes: 14 additions & 0 deletions packages/rocketchat-external/app/client/views/avatar.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Template.avatar.helpers
imageUrl: ->
username = this.username
if not username? and this.userId?
username = Meteor.users.findOne(this.userId)?.username

if not username?
return

Session.get "avatar_random_#{username}"

url = getAvatarUrlFromUsername(username)

return "background-image:url(#{url});"
5 changes: 5 additions & 0 deletions packages/rocketchat-external/app/client/views/avatar.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template name="avatar">
<div class="avatar">
<div class="avatar-image" style="{{imageUrl}}"></div>
</div>
</template>
18 changes: 18 additions & 0 deletions packages/rocketchat-external/app/client/views/main.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<head>
<title>Rocket.Chat</title>
<meta charset="utf-8" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="expires" content="-1" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="fragment" content="!" />
<meta name="distribution" content="global" />
<meta name="rating" content="general" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
</head>

<body>
</body>

<template name="main">
{{> Template.dynamic template=center}}
</template>
Loading