# Convert a color `value` as integer to a hex color (e.g. 255 to #0000ff) @colourToHex = (value) -> hex = parseInt(value).toString(16) hex = "0" + hex while hex.length < 6 "##{hex}" # retrieve account for selected user @getCurrentUserFromSession = -> Meteor.Users.findOne("userId": getInSession("userId")) @getInSession = (k) -> SessionAmplify.get k @getMeetingName = -> meetName = getInSession("meetingName") # check if we actually have one in the session if meetName? then meetName # great return it, no database query else # we need it from the database meet = Meteor.Meetings.findOne({}) if meet?.meetingName setInSession "meetingName", meet?.meetingName # store in session for fast access next time meet?.meetingName else null # Finds the names of all people the current user is in a private conversation with # Removes yourself and duplicates if they exist @getPrivateChatees = -> me = getInSession("userId") users = Meteor.Users.find().fetch() people = Meteor.Chat.find({$or: [{'message.from_userid': me, 'message.chat_type': 'PRIVATE_CHAT'},{'message.to_userid': me, 'message.chat_type': 'PRIVATE_CHAT'}] }).fetch() formattedUsers = null formattedUsers = (u for u in users when (do -> return false if u.userId is me found = false for chatter in people # if u.userId is chatter.message.to_userid or u.userId is chatter.message.from_userid if u._id is chatter.message.to_userid or u._id is chatter.message.from_userid found = true found ) ) if formattedUsers? then formattedUsers else [] @getTime = -> # returns epoch in ms (new Date).valueOf() @getTimeOfJoining = -> Meteor.Users.findOne(_id: getInSession "DBID")?.user?.time_of_joining @getUsersName = -> name = getInSession("userName") # check if we actually have one in the session if name? then name # great return it, no database query else # we need it from the database user = Meteor.Users.findOne({'userId': getInSession("userId")}) if user?.user?.name setInSession "userName", user.user.name # store in session for fast access next time user.user.name else null Handlebars.registerHelper "colourToHex", (value) => @window.colourToHex(value) Handlebars.registerHelper 'equals', (a, b) -> # equals operator was dropped in Meteor's migration from Handlebars to Spacebars a is b Handlebars.registerHelper "getCurrentMeeting", -> Meteor.Meetings.findOne() Handlebars.registerHelper "getCurrentSlide", -> currentPresentation = Meteor.Presentations.findOne({"presentation.current": true}) presentationId = currentPresentation?.presentation?.id Meteor.Slides.find({"presentationId": presentationId, "slide.current": true}) # retrieve account for selected user Handlebars.registerHelper "getCurrentUser", => @window.getCurrentUserFromSession() Handlebars.registerHelper "getHandRaiseStats", -> numRaised = Meteor.Users.find({'user.raise_hand':true}).fetch().length total = Meteor.Users.find().fetch().length percentageRaised = numRaised/total if numRaised > 0 "#{numRaised} Hands Raised (#{percentageRaised}% of Attendees)" else false # Allow access through all templates Handlebars.registerHelper "getInSession", (k) -> SessionAmplify.get k Handlebars.registerHelper "getMeetingName", -> window.getMeetingName() Handlebars.registerHelper "getShapesForSlide", -> currentSlide = getCurrentSlideDoc() # try to reuse the lines above Meteor.Shapes.find({whiteboardId: currentSlide?.slide?.id}) # retrieves all users in the meeting Handlebars.registerHelper "getUsersInMeeting", -> Meteor.Users.find({}) Handlebars.registerHelper "isCurrentUser", (id) -> id is getInSession("userId") Handlebars.registerHelper "meetingIsRecording", -> Meteor.Meetings.findOne()?.recorded # Should only ever have one meeting, so we dont need any filter and can trust result #1 Handlebars.registerHelper "isCurrentUserMuted", -> getInSession "isMuted" Handlebars.registerHelper "isCurrentUserRaisingHand", -> user = Meteor.Users.findOne({userId:getInSession("userId")}) user?.user?.raise_hand Handlebars.registerHelper "isCurrentUserSharingAudio", -> user = Meteor.Users.findOne({userId:getInSession("userId")}) user?.user?.voiceUser?.joined Handlebars.registerHelper "isCurrentUserSharingVideo", -> user = Meteor.Users.findOne({userId:getInSession("userId")}) user?.user?.webcam_stream?.length isnt 0 Handlebars.registerHelper "isCurrentUserTalking", -> user = Meteor.Users.findOne({userId:getInSession("userId")}) user?.user?.voiceUser?.talking Handlebars.registerHelper "isUserSharingAudio", (u) -> if u? user = Meteor.Users.findOne({userId:u.userid}) user?.user?.voiceUser?.joined else return false Handlebars.registerHelper "isUserListenOnly", (u) -> if u? user = Meteor.Users.findOne({userId:u.userid}) user?.user?.listenOnly else return false Handlebars.registerHelper "isUserSharingVideo", (u) -> u.webcam_stream?.length isnt 0 Handlebars.registerHelper "isUserTalking", (u) -> if u? user = Meteor.Users.findOne({userId:u.userid}) user.user?.voiceUser?.talking else return false Handlebars.registerHelper "isUserMuted", (u) -> if u? user = Meteor.Users.findOne({userId:u.userid}) user.user.voiceUser?.muted else return false Handlebars.registerHelper "messageFontSize", -> style: "font-size: #{getInSession("messageFontSize")}px;" Handlebars.registerHelper "pointerLocation", -> currentPresentation = Meteor.Presentations.findOne({"presentation.current": true}) currentPresentation?.pointer Handlebars.registerHelper "setInSession", (k, v) -> SessionAmplify.set k, v Handlebars.registerHelper "visibility", (section) -> if getInSession "display_#{section}" style: 'display:block' else style: 'display:none' # transform plain text links into HTML tags compatible with Flash client @linkify = (str) -> www = /(^|[^\/])(www\.[\S]+($|\b))/img http = /\b(https?:\/\/[0-9a-z+|.,:;\/&?_~%#=@!-]*[0-9a-z+|\/&_~%#=@-])/img str = str.replace http, "$1" str = str.replace www, "$1$2" # Creates a 'tab' object for each person in chat with # adds public and options tabs to the menu @makeTabs = -> privTabs = getPrivateChatees().map (u, index) -> newObj = { userId: u.userId name: u.user.name gotMail: false class: "privateChatTab" } tabs = [ {userId: "PUBLIC_CHAT", name: "Public", gotMail: false, class: "publicChatTab"}, {userId: "OPTIONS", name: "Options", gotMail: false, class: "optionsChatTab"} ].concat privTabs @setInSession = (k, v) -> SessionAmplify.set k, v Meteor.methods sendMeetingInfoToClient: (meetingId, userId) -> setInSession("userId", userId) setInSession("meetingId", meetingId) setInSession("currentChatId", meetingId) setInSession("meetingName", null) setInSession("bbbServerVersion", "0.90") setInSession("userName", null) @toggleCam = (event) -> # Meteor.Users.update {_id: context._id} , {$set:{"user.sharingVideo": !context.sharingVideo}} # Meteor.call('userToggleCam', context._id, !context.sharingVideo) @toggleChatbar = -> setInSession "display_chatbar", !getInSession "display_chatbar" @toggleMic = (event) -> if getInSession "isSharingAudio" # only allow muting/unmuting if they are in the call u = Meteor.Users.findOne({userId:getInSession("userId")}) if u? # format: meetingId, userId, requesterId, mutedBoolean # TODO: insert the requesterId - the user who requested the muting of userId (might be a moderator) Meteor.call('publishMuteRequest', u.meetingId, u.userId, u.userId, not u.user.voiceUser.muted) setInSession "isMuted", not u.user.voiceUser.muted @toggleNavbar = -> setInSession "display_navbar", !getInSession "display_navbar" # toggle state of session variable @toggleUsersList = -> setInSession "display_usersList", !getInSession "display_usersList" @toggleVoiceCall = (event) -> if getInSession "isSharingAudio" hangupCallback = -> console.log "left voice conference" # sometimes we can hangup before the message that the user stopped talking is received so lets set it manually, otherwise they might leave the audio call but still be registered as talking Meteor.call("userStopAudio", getInSession("meetingId"),getInSession("userId")) setInSession "isSharingAudio", false # update to no longer sharing webrtc_hangup hangupCallback # sign out of call else # create voice call params username = "#{getInSession("userId")}-bbbID-#{getUsersName()}" # voicePin = Meteor.Meetings.findOne()?.voiceConf # voiceBridge = if voicePin? then voicePin else "0" voiceBridge = Meteor.Meetings.findOne({}).voiceConf # need to know this info for all meetings #TODO server = null joinCallback = (message) -> console.log JSON.stringify message Meteor.call("userShareAudio", getInSession("meetingId"),getInSession("userId")) console.log "joined audio call" console.log Meteor.Users.findOne(userId:getInSession("userId")) setInSession "isSharingAudio", true webrtc_call(username, voiceBridge, server, joinCallback) # make the call return false @toggleWhiteBoard = -> setInSession "display_whiteboard", !getInSession "display_whiteboard" # Starts the entire logout procedure. # meeting: the meeting the user is in # the user's userId @userLogout = (meeting, user) -> Meteor.call("userLogout", meeting, user) # Clear the local user session and redirect them away setInSession("userId", null) setInSession("meetingId", null) setInSession("currentChatId", null) setInSession("meetingName", null) setInSession("bbbServerVersion", null) setInSession("userName", null) setInSession "display_navbar", false # needed to hide navbar when the layout template renders Router.go('logout') # navigate to logout # color can be a number (a hex converted to int) or a string (e.g. "#ffff00") @formatColor = (color) -> color ?= "0" # default value if !color.toString().match(/\#.*/) color = colourToHex(color) color # thickness can be a number (e.g. "2") or a string (e.g. "2px") @formatThickness = (thickness) -> thickness ?= "1" # default value if !thickness.toString().match(/.*px$/) "#" + thickness + "px" # leading "#" - to be compatible with Firefox thickness # applies zooming to the stroke thickness @zoomStroke = (thickness) -> currentSlide = @getCurrentSlideDoc() ratio = (currentSlide?.slide.width_ratio + currentSlide?.slide.height_ratio) / 2 thickness * 100 / ratio @getCurrentSlideDoc = -> # returns only one document currentPresentation = Meteor.Presentations.findOne({"presentation.current": true}) presentationId = currentPresentation?.presentation?.id currentSlide = Meteor.Slides.findOne({"presentationId": presentationId, "slide.current": true})