diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee
index 341ef2d2e..f001a6330 100644
--- a/app/lib/surface/Surface.coffee
+++ b/app/lib/surface/Surface.coffee
@@ -615,7 +615,7 @@ module.exports = Surface = class Surface extends CocoClass
screenshot: (scale=0.25, format='image/jpeg', quality=0.8, zoom=2) ->
# TODO: get screenshots working again
# Quality doesn't work with image/png, just image/jpeg and image/webp
- [w, h] = [@camera.canvasWidth, @camera.canvasHeight]
+ [w, h] = [@camera.canvasWidth * @camera.canvasScaleFactorX, @camera.canvasHeight * @camera.canvasScaleFactorY]
margin = (1 - 1 / zoom) / 2
@webGLStage.cache margin * w, margin * h, w / zoom, h / zoom, scale * zoom
imageData = @webGLStage.cacheCanvas.toDataURL(format, quality)
diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index 5ea02ceed..b0b94e1af 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -484,6 +484,7 @@
subscribe: "buy a CodeCombat subscription"
subscribe_suffix: "and we'll be happy to help you with your code."
subscriber_support: "Since you're a CodeCombat subscriber, your email will get our priority support."
+ screenshot_included: "Screenshot included."
where_reply: "Where should we reply?"
send: "Send Feedback"
contact_candidate: "Contact Candidate" # Deprecated
diff --git a/app/templates/core/contact.jade b/app/templates/core/contact.jade
index 517a4b41b..ec56aae3e 100644
--- a/app/templates/core/contact.jade
+++ b/app/templates/core/contact.jade
@@ -24,6 +24,11 @@ block modal-body-content
label.control-label(for="contact-message", data-i18n="general.message") Message
textarea#contact-message.form-control(name="message", rows=8)
+ #contact-screenshot.secret
+ a(target='_blank', data-i18n="contact.screenshot_included") Screenshot included.
+ br
+ img.pull-left(width=100)
+
block modal-footer-content
span.sending-indicator.pull-left.secret(data-i18n="common.sending") Sending...
a(href='#', data-dismiss="modal", aria-hidden="true", data-i18n="common.cancel").btn Cancel
diff --git a/app/templates/play/level.jade b/app/templates/play/level.jade
index de3dbe5dc..b9329fc29 100644
--- a/app/templates/play/level.jade
+++ b/app/templates/play/level.jade
@@ -37,4 +37,4 @@
if !me.get('anonymous')
#play-footer(class=me.isPremium() ? "premium" : "")
p(class='footer-link-text')
- a(title='Send CodeCombat a message', tabindex=-1, data-toggle="coco-modal", data-target="core/ContactModal", data-i18n="nav.contact") Contact
+ a.contact-link(title='Send CodeCombat a message', tabindex=-1, data-i18n="nav.contact") Contact
diff --git a/app/views/core/ContactModal.coffee b/app/views/core/ContactModal.coffee
index f74458a00..1a7fa17c3 100644
--- a/app/views/core/ContactModal.coffee
+++ b/app/views/core/ContactModal.coffee
@@ -32,6 +32,19 @@ module.exports = class ContactModal extends ModalView
contactMessage = forms.formToObject @$el
res = tv4.validateMultiple contactMessage, contactSchema
return forms.applyErrorsToForm @$el, res.errors unless res.valid
+ @populateBrowserData contactMessage
window.tracker?.trackEvent 'Sent Feedback', message: contactMessage
sendContactMessage contactMessage, @$el
$.post "/db/user/#{me.id}/track/contact_codecombat"
+
+ populateBrowserData: (context) ->
+ if $.browser
+ context.browser = "#{$.browser.platform} #{$.browser.name} #{$.browser.versionNumber}"
+ context.screenSize = "#{screen?.width ? $(window).width()} x #{screen?.height ? $(window).height()}"
+ context.screenshotURL = @screenshotURL
+
+ updateScreenshot: ->
+ return unless @screenshotURL
+ screenshotEl = @$el.find('#contact-screenshot').removeClass('secret')
+ screenshotEl.find('a').prop('href', @screenshotURL)
+ screenshotEl.find('img').prop('src', @screenshotURL)
diff --git a/app/views/play/level/PlayLevelView.coffee b/app/views/play/level/PlayLevelView.coffee
index b0960438c..c481692d4 100644
--- a/app/views/play/level/PlayLevelView.coffee
+++ b/app/views/play/level/PlayLevelView.coffee
@@ -36,6 +36,7 @@ VictoryModal = require './modal/VictoryModal'
HeroVictoryModal = require './modal/HeroVictoryModal'
InfiniteLoopModal = require './modal/InfiniteLoopModal'
LevelSetupManager = require 'lib/LevelSetupManager'
+ContactModal = require 'views/core/ContactModal'
PROFILE_ME = false
@@ -81,6 +82,7 @@ module.exports = class PlayLevelView extends RootView
'click #level-done-button': 'onDonePressed'
'click #stop-real-time-playback-button': -> Backbone.Mediator.publish 'playback:stop-real-time-playback', {}
'click #fullscreen-editor-background-screen': (e) -> Backbone.Mediator.publish 'tome:toggle-maximize', {}
+ 'click .contact-link': 'onContactClicked'
shortcuts:
'ctrl+s': 'onCtrlS'
@@ -477,6 +479,20 @@ module.exports = class PlayLevelView extends RootView
return unless screenshot = @surface?.screenshot()
session.save {screenshot: screenshot}, {patch: true, type: 'PUT'}
+ onContactClicked: (e) ->
+ @openModalView contactModal = new ContactModal()
+ screenshot = @surface.screenshot(1, 'image/png', 1.0, 1)
+ body =
+ b64png: screenshot.replace 'data:image/png;base64,', ''
+ filename: "screenshot-#{@levelID}-#{_.string.slugify((new Date()).toString())}.png"
+ path: "db/user/#{me.id}"
+ mimetype: 'image/png'
+ contactModal.screenshotURL = "http://codecombat.com/file/#{body.path}/#{body.filename}"
+ window.screenshot = screenshot
+ window.screenshotURL = contactModal.screenshotURL
+ $.ajax '/file', type: 'POST', data: body, success: (e) ->
+ contactModal.updateScreenshot?()
+
# Dynamic sound loading
onNewWorld: (e) ->
diff --git a/server/routes/contact.coffee b/server/routes/contact.coffee
index 2ae8564fc..9804e79da 100644
--- a/server/routes/contact.coffee
+++ b/server/routes/contact.coffee
@@ -10,13 +10,19 @@ module.exports.setup = (app) ->
app.post '/contact', (req, res) ->
return res.end() unless req.user
#log.info "Sending mail from #{req.body.email} saying #{req.body.message}"
- createMailContext req.body.email, req.body.message, req.user, req.body.recipientID, req.body.subject, (context) ->
+ createMailContext req, (context) ->
sendwithus.api.send context, (err, result) ->
if err
log.error "Error sending contact form email: #{err.message or err}"
return res.end()
-createMailContext = (sender, message, user, recipientID, subject, done) ->
+createMailContext = (req, done) ->
+ sender = req.body.sender
+ message = req.body.message
+ user = req.user
+ recipientID = req.body.recipientID
+ subject = req.body.subject
+
level = if user?.get('points') > 0 then Math.floor(5 * Math.log((1 / 100) * (user.get('points') + 100))) + 1 else 0
premium = user?.isPremium()
content = """
@@ -25,6 +31,8 @@ createMailContext = (sender, message, user, recipientID, subject, done) ->
--
#{user.get('name') or 'Anonymous'} - Level #{level}#{if premium then ' - Subscriber' else ''}
"""
+ if req.body.browser
+ content += "\n#{req.body.browser} - #{req.body.screenSize}"
context =
email_id: sendwithus.templates.plain_text_email
@@ -55,6 +63,8 @@ createMailContext = (sender, message, user, recipientID, subject, done) ->
# TODO: try automatically including Surface screenshot if opening contact form from level?
], (err, results) ->
console.error "Error getting contact message context for #{sender}: #{err}" if err
+ if req.body.screenshotURL
+ context.email_data.content += "\n
"
done context
fetchRecentSessions = (user, context, callback) ->
@@ -63,7 +73,6 @@ fetchRecentSessions = (user, context, callback) ->
sort = changed: -1
LevelSession.find(query).select(projection).sort(sort).limit(3).lean().exec (err, sessions) ->
return callback err if err
- console.log 'found', sessions.length, 'sessions'
for s in sessions
if s.playtime < 120 then playtime = "#{s.playtime}s played"
else if s.playtime < 7200 then playtime = "#{Math.round(s.playtime / 60)}m played"