habitica/src/app/party.coffee

203 lines
7.7 KiB
CoffeeScript
Raw Normal View History

_ = require('underscore')
helpers = require './helpers'
partyUnsubscribe = (model, cb) ->
if window?
throw "unsubscribe requires cb" unless cb?
subs = model._subs()
subs.concat cb
model.unsubscribe.apply(model, subs)
else
cb()
###
2013-02-20 00:36:57 +00:00
Subscribe to the user, the users's party (meta info like party name, member ids, etc), and the party's members. 3 subscriptions.
1) If the user is solo, just subscribe to the user.
2) If in a an empty party, just subscribe to the user & party meta.
3) If full party, subscribe to everything.
Note a strange hack - we subscribe to queries incrementally. First self, then party, then party members.
Party members come with limited fields, so you can't hack their stuff. Strangely, subscribing to the members after
already subscribing to self limits self's fields to the fields which members are limited to. As a result, we have
to re-subscribe to self to get all the fields (otherwise everything breaks). Weirdly, this last subscription doesn't
do the opposite - granting all the fields back to members. I dont' know what's going on here
Another issue: `model.unsubscribe(selfQ)` would seem to mitigate the above, so we at least don't have a stray
subscription floating around - but alas, it doesn't seem to work (or at least never calls the callback)
###
module.exports.partySubscribe = partySubscribe = (page, model, params, next, cb) ->
2013-02-08 00:13:14 +00:00
# unsubscribe from everything - we're starting over
# partyUnsubscribe model, ->
2013-02-18 20:26:10 +00:00
# Restart subscription to the main user
selfQ = model.query('users').withId (model.get('_userId') or model.session.userId) # see http://goo.gl/TPYIt
selfQ.fetch (err, user) ->
return next(err) if err
unless user.get()
#return next("User not found - this shouldn't be happening!")
2013-04-24 17:21:59 +00:00
console.error "User not found - this shouldn't be happening!"
return page.redirect('/logout') #delete model.session.userId
finished = (descriptors, paths) ->
2013-05-02 20:09:50 +00:00
descriptors.push 'tavern'; paths.push '_tavern'
model.subscribe.apply model, descriptors.concat ->
[err, refs] = [arguments[0], arguments]
return next(err) if err
_.each paths, (path, idx) -> model.ref path, refs[idx+1]
cb()
# Attempted handling for 'party of undefined' error, which is caused by bustedSession (see derby-auth).
# Theoretically simply reloading the page should restore model.at('_userId') and the second load should work just fine
# bustedSession victims might hit a redirection loop if I'm wrong :/
# return page.redirect('/') unless uObj
partyId = user.get('party.current')
# (1) Solo player
return finished([selfQ], ['_user']) unless partyId
2013-02-18 20:26:10 +00:00
# User in a party
partyQ = model.query('parties').withId(partyId)
partyQ.fetch (err, party) ->
return next(err) if err
members = party.get('members')
2013-02-18 20:26:10 +00:00
## (2) Party has no members, just subscribe to the party itself
return finished([partyQ, selfQ], ['_party', '_user']) if _.isEmpty(members)
2013-02-18 20:26:10 +00:00
## (3) Party has members, subscribe to those users too
membersQ = model.query('users').party(members)
return finished [partyQ, membersQ, selfQ], ['_party', '_partyMembers', '_user']
2013-05-02 19:16:09 +00:00
module.exports.app = (appExports, model, app) ->
character = require './character'
browser = require './browser'
helpers = require './helpers'
user = model.at('_user')
model.on 'set', '_user.party.invitation', (after, before) ->
if !before? and after? # they just got invited
partyQ = model.query('parties').withId(after)
partyQ.fetch (err, party) ->
return next(err) if err
model.ref '_party', party
browser.resetDom(model)
appExports.partyCreate = ->
newParty = model.get("_newParty")
id = model.add 'parties', { name: newParty, leader: user.get('id'), members: [user.get('id')], invites:[] }
user.set 'party', {current: id, invitation: null, leader: true}, ->
2013-02-19 22:33:34 +00:00
window.location.reload true
# partySubscribe model, -> $('#party-modal').modal('show')
appExports.partyInvite = ->
id = model.get('_newPartyMember').replace(/[\s"]/g, '')
return if _.isEmpty(id)
2013-02-27 21:21:06 +00:00
model.query('users').party([id]).fetch (err, res) ->
2013-02-05 21:11:28 +00:00
throw err if err
2013-02-27 21:21:06 +00:00
u = res.at(0).get()
if !u?
model.set "_partyError", "User with id #{id} not found."
return
else if u.party.current? or u.party.invitation?
model.set "_partyError", "User already in a party or pending invitation."
return
else
p = model.at '_party'
2013-02-27 21:21:06 +00:00
#p.push "invites", id
$.bootstrapGrowl "Invitation Sent."
$('#party-modal').modal('hide')
2013-02-27 21:21:06 +00:00
model.set "users.#{id}.party.invitation", p.get('id'), -> window.location.reload(true)
#model.set '_newPartyMember', ''
#partySubscribe model
appExports.partyAccept = ->
partyId = user.get('party.invitation')
2013-02-08 00:13:14 +00:00
user.set 'party.invitation', null
user.set 'party.current', partyId
2013-02-27 21:21:06 +00:00
model.at("parties.#{partyId}.members").push user.get('id'), -> window.location.reload(true)
# model.query('parties').withId(partyId).fetch (err, p) ->
# members = p.get('members')
# members.push user.get('id')
# p.set 'members', members, ->
# window.location.reload true
# partySubscribe model, ->
# p = model.at('_party')
# p.push 'members', user.get('id')
appExports.partyReject = ->
user.set 'party.invitation', null
browser.resetDom(model)
2013-02-05 21:11:28 +00:00
# TODO splice parties.*.invites[key]
# TODO notify sender
appExports.partyLeave = ->
2013-02-05 23:52:29 +00:00
id = user.set 'party.current', null
p = model.at '_party'
members = p.get('members')
index = members.indexOf(user.get('id'))
2013-02-06 03:27:19 +00:00
members.splice(index,1)
p.set 'members', members, ->
if (members.length == 0)
2013-02-19 22:33:34 +00:00
# last member out, kill the party
model.del "parties.#{id}", -> window.location.reload true
else
2013-02-19 22:33:34 +00:00
window.location.reload true
# model.set '_party', null
# model.set '_partyMembers', null
# partyUnsubscribe model, ->
# selfQ = model.query('users').withId model.get('_userId') #or model.session.userId # see http://goo.gl/TPYIt
# selfQ.subscribe (err, u) ->
# model.ref '_user', u
# browser.resetDom model
2013-05-02 19:16:09 +00:00
###
Chat Functionality
###
2013-05-02 20:09:50 +00:00
sendChat = (path, input) ->
chat = model.at path
text = model.get input
# Check for non-whitespace characters
return unless /\S/.test text
chat.unshift
id: helpers.uuid() #FIXME model.id() isn't working, temporary solution https://github.com/lefnire/habitrpg/issues/891#issuecomment-17458776
uuid: user.get('id')
contributor: user.get('backer.contributor')
npc: user.get('backer.npc')
text: text
user: helpers.username(model.get('_user.auth'), model.get('_user.profile.name'))
timestamp: +new Date
2013-05-02 20:09:50 +00:00
model.set(input, '')
2013-05-02 19:16:09 +00:00
chat.remove 200 # keep a max messages cap
model.on 'unshift', '_party.chat', -> $('.chat-message').tooltip()
model.on 'unshift', '_tavern.chat.messages', -> $('.chat-message').tooltip()
2013-05-02 20:09:50 +00:00
appExports.partySendChat = ->
sendChat('_party.chat', '_chatMessage')
model.set '_user.party.lastMessageSeen', model.get('_party.chat')[0].id
appExports.tavernSendChat = ->
model.setNull '_tavern.chat', {messages:[]} #we can remove this later, first time run only
sendChat('_tavern.chat.messages', '_tavernMessage')
appExports.tavernMessageKeyup = (e, el, next) ->
return next() unless e.keyCode is 13
appExports.tavernSendChat()
2013-05-02 19:16:09 +00:00
app.on 'render', (ctx) ->
$('#party-tab-link').on 'shown', (e) ->
messages = model.get('_party.chat')
return false unless messages?.length > 0
model.set '_user.party.lastMessageSeen', messages[0].id
appExports.gotoPartyChat = ->
model.set '_gamePane', true, ->
$('#party-tab-link').tab('show')