From 08cb87c84d59c88c428fe1e425c67f8e5f00b6cb Mon Sep 17 00:00:00 2001 From: Nick Winter Date: Fri, 19 Dec 2014 18:37:42 -0800 Subject: [PATCH] Automatically take screenshots when submitting contact form from level view. --- app/lib/surface/Surface.coffee | 2 +- app/locale/en.coffee | 1 + app/templates/core/contact.jade | 5 +++++ app/templates/play/level.jade | 2 +- app/views/core/ContactModal.coffee | 13 +++++++++++++ app/views/play/level/PlayLevelView.coffee | 16 ++++++++++++++++ server/routes/contact.coffee | 15 ++++++++++++--- 7 files changed, 49 insertions(+), 5 deletions(-) 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"