diff options
author | Daniel Calviño Sánchez <danxuliu@gmail.com> | 2018-11-27 11:40:12 +0100 |
---|---|---|
committer | Joas Schilling <coding@schilljs.com> | 2018-11-28 12:48:51 +0100 |
commit | 252c53e780a3557f073981cea78c8982f39745e5 (patch) | |
tree | 5c8910b73c6b9318bac7e99a06c7f5690ada3e08 | |
parent | da13fd1d8f493e231aa348d60124bb22baf69a3d (diff) |
Move ChatView to precompiled Handlebars templates
In Nextcloud 15 the default Content Security Policy disallows unsafe
eval expressions, so Handlebars templates can no longer be compiled at
runtime.
For the time being that default Content Security Policy was lifted for
Talk so "Handlebars.compile" could still be used. However, this only
applies to Talk itself; when using Talk components in other apps they
must abide to the Content Security Policy of those apps. As ChatView is
going to be used in the Files app it has been moved to precompiled
Handlebars templates (which are still compatible with the regular Talk
UI).
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
-rwxr-xr-x | compile-handlebars-templates.sh | 2 | ||||
-rw-r--r-- | js/views/chatview.js | 57 | ||||
-rw-r--r-- | js/views/templates.js | 89 | ||||
-rw-r--r-- | js/views/templates/chatview.handlebars | 6 | ||||
-rw-r--r-- | js/views/templates/chatview_add_comment.handlebars | 19 | ||||
-rw-r--r-- | js/views/templates/chatview_comment.handlebars | 10 | ||||
-rw-r--r-- | lib/PublicShareAuth/TemplateLoader.php | 1 | ||||
-rw-r--r-- | templates/index-public.php | 1 | ||||
-rw-r--r-- | templates/index.php | 1 |
9 files changed, 140 insertions, 46 deletions
diff --git a/compile-handlebars-templates.sh b/compile-handlebars-templates.sh index 663a5bd83..632488aff 100755 --- a/compile-handlebars-templates.sh +++ b/compile-handlebars-templates.sh @@ -4,3 +4,5 @@ export PATH=./node_modules/.bin/:$PATH handlebars -n OCA.VideoCalls.Admin.Templates js/admin/templates/ -f js/admin/templates.js + +handlebars -n OCA.SpreedMe.Views.Templates js/views/templates/ -f js/views/templates.js diff --git a/js/views/chatview.js b/js/views/chatview.js index eccf5f858..2a7106337 100644 --- a/js/views/chatview.js +++ b/js/views/chatview.js @@ -1,4 +1,4 @@ -/* global autosize, Handlebars, Marionette, moment, OC, OCA, OCP */ +/* global autosize, Marionette, moment, OC, OCA, OCP */ /** * @@ -21,52 +21,12 @@ * */ -(function(OCA, OC, OCP, Marionette, Handlebars, autosize, moment) { +(function(OCA, OC, OCP, Marionette, autosize, moment) { 'use strict'; OCA.SpreedMe = OCA.SpreedMe || {}; OCA.SpreedMe.Views = OCA.SpreedMe.Views || {}; - var TEMPLATE = - '<ul class="comments">' + - '</ul>' + - '<div class="emptycontent"><div class="icon-comment"></div>' + - '<p>{{emptyResultLabel}}</p></div>' + - '<div class="loading hidden" style="height: 50px"></div>'; - - var ADD_COMMENT_TEMPLATE = - '<div class="newCommentRow comment">' + - ' <div class="authorRow currentUser">' + - ' <div class="avatar" data-user-id="{{actorId}}"></div>' + - ' {{#if actorId}}' + - ' <div class="author">{{actorDisplayName}}</div>' + - ' {{else}}' + - ' <div class="guest-name"></div>' + - ' {{/if}}' + - ' </div>' + - ' <form class="newCommentForm">' + - ' <div contentEditable="true" class="message" data-placeholder="{{newMessagePlaceholder}}">{{message}}</div>' + - ' <input class="submit icon-confirm has-tooltip" type="submit" value="" title="{{submitText}}"/>' + - ' <div class="submitLoading icon-loading-small hidden"></div>'+ - ' {{#if actorId}}' + - ' <button class="share icon-add has-tooltip" title="{{shareText}}"></button>' + - ' <div class="shareLoading icon-loading-small hidden"></div>'+ - ' {{/if}}' + - ' </form>' + - '</div>'; - - var COMMENT_TEMPLATE = - '<li class="comment{{#if isNotSystemMessage}}{{else}} systemMessage{{/if}}" data-id="{{id}}">' + - ' <div class="authorRow{{#if isUserAuthor}} currentUser{{/if}}{{#if isGuest}} guestUser{{/if}}">' + - ' {{#if isNotSystemMessage}}' + - ' <div class="avatar" data-user-id="{{#if isGuest}}{{else}}{{actorId}}{{/if}}" data-user-display-name="{{actorDisplayName}}"> </div>' + - ' <div class="author">{{actorDisplayName}}</div>' + - ' {{/if}}' + - ' <div class="date has-tooltip{{#if relativeDate}} live-relative-timestamp{{/if}}" data-timestamp="{{timestamp}}" title="{{altDate}}">{{date}}</div>' + - ' </div>' + - ' <div class="message">{{{formattedMessage}}}</div>' + - '</li>'; - var ChatView = Marionette.View.extend({ groupedMessages: 0, @@ -201,14 +161,19 @@ document.execCommand('insertText', false, text); }, - template: Handlebars.compile(TEMPLATE), + template: function(context) { + // OCA.SpreedMe.Views.Templates may not have been initialized when + // this view is initialized, so the template can not be directly + // assigned. + return OCA.SpreedMe.Views.Templates['chatview'](context); + }, templateContext: { emptyResultLabel: t('spreed', 'No messages yet, start the conversation!') }, addCommentTemplate: function(params) { if (!this._addCommentTemplate) { - this._addCommentTemplate = Handlebars.compile(ADD_COMMENT_TEMPLATE); + this._addCommentTemplate = OCA.SpreedMe.Views.Templates['chatview_add_comment']; } return this._addCommentTemplate(_.extend({ @@ -222,7 +187,7 @@ commentTemplate: function(params) { if (!this._commentTemplate) { - this._commentTemplate = Handlebars.compile(COMMENT_TEMPLATE); + this._commentTemplate = OCA.SpreedMe.Views.Templates['chatview_comment']; } params = _.extend({ @@ -756,4 +721,4 @@ OCA.SpreedMe.Views.ChatView = ChatView; -})(OCA, OC, OCP, Marionette, Handlebars, autosize, moment); +})(OCA, OC, OCP, Marionette, autosize, moment); diff --git a/js/views/templates.js b/js/views/templates.js new file mode 100644 index 000000000..ee6175bc1 --- /dev/null +++ b/js/views/templates.js @@ -0,0 +1,89 @@ +(function() { + var template = Handlebars.template, templates = OCA.SpreedMe.Views.Templates = OCA.SpreedMe.Views.Templates || {}; +templates['chatview'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { + var helper; + + return "<ul class=\"comments\"></ul>\n<div class=\"emptycontent\">\n <div class=\"icon-comment\"></div>\n <p>" + + container.escapeExpression(((helper = (helper = helpers.emptyResultLabel || (depth0 != null ? depth0.emptyResultLabel : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"emptyResultLabel","hash":{},"data":data}) : helper))) + + "</p>\n</div>\n<div class=\"loading hidden\" style=\"height: 50px\"></div>\n"; +},"useData":true}); +templates['chatview_add_comment'] = template({"1":function(container,depth0,helpers,partials,data) { + var helper; + + return " <div class=\"author\">" + + container.escapeExpression(((helper = (helper = helpers.actorDisplayName || (depth0 != null ? depth0.actorDisplayName : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"actorDisplayName","hash":{},"data":data}) : helper))) + + "</div>\n"; +},"3":function(container,depth0,helpers,partials,data) { + return " <div class=\"guest-name\"></div>\n"; +},"5":function(container,depth0,helpers,partials,data) { + var helper; + + return " <button class=\"share icon-add has-tooltip\" title=\"" + + container.escapeExpression(((helper = (helper = helpers.shareText || (depth0 != null ? depth0.shareText : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"shareText","hash":{},"data":data}) : helper))) + + "\"></button>\n <div class=\"shareLoading icon-loading-small hidden\"></div>\n"; +},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return "<div class=\"newCommentRow comment\">\n <div class=\"authorRow currentUser\">\n <div class=\"avatar\" data-user-id=\"" + + alias4(((helper = (helper = helpers.actorId || (depth0 != null ? depth0.actorId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"actorId","hash":{},"data":data}) : helper))) + + "\"></div>\n" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.actorId : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.program(3, data, 0),"data":data})) != null ? stack1 : "") + + " </div>\n <form class=\"newCommentForm\">\n <div contentEditable=\"true\" class=\"message\" data-placeholder=\"" + + alias4(((helper = (helper = helpers.newMessagePlaceholder || (depth0 != null ? depth0.newMessagePlaceholder : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"newMessagePlaceholder","hash":{},"data":data}) : helper))) + + "\">" + + alias4(((helper = (helper = helpers.message || (depth0 != null ? depth0.message : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"message","hash":{},"data":data}) : helper))) + + "</div>\n <input class=\"submit icon-confirm has-tooltip\" type=\"submit\" value=\"\" title=\"" + + alias4(((helper = (helper = helpers.submitText || (depth0 != null ? depth0.submitText : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"submitText","hash":{},"data":data}) : helper))) + + "\"/>\n <div class=\"submitLoading icon-loading-small hidden\"></div>\n" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.actorId : depth0),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " </form>\n</div>\n"; +},"useData":true}); +templates['chatview_comment'] = template({"1":function(container,depth0,helpers,partials,data) { + return ""; +},"3":function(container,depth0,helpers,partials,data) { + return " systemMessage"; +},"5":function(container,depth0,helpers,partials,data) { + return " currentUser"; +},"7":function(container,depth0,helpers,partials,data) { + return " guestUser"; +},"9":function(container,depth0,helpers,partials,data) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return " <div class=\"avatar\" data-user-id=\"" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isGuest : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.program(10, data, 0),"data":data})) != null ? stack1 : "") + + "\" data-user-display-name=\"" + + alias4(((helper = (helper = helpers.actorDisplayName || (depth0 != null ? depth0.actorDisplayName : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"actorDisplayName","hash":{},"data":data}) : helper))) + + "\"></div>\n <div class=\"author\">" + + alias4(((helper = (helper = helpers.actorDisplayName || (depth0 != null ? depth0.actorDisplayName : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"actorDisplayName","hash":{},"data":data}) : helper))) + + "</div>\n"; +},"10":function(container,depth0,helpers,partials,data) { + var helper; + + return container.escapeExpression(((helper = (helper = helpers.actorId || (depth0 != null ? depth0.actorId : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"actorId","hash":{},"data":data}) : helper))); +},"12":function(container,depth0,helpers,partials,data) { + return " live-relative-timestamp"; +},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return "<li class=\"comment" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isNotSystemMessage : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.program(3, data, 0),"data":data})) != null ? stack1 : "") + + "\" data-id=\"" + + alias4(((helper = (helper = helpers.id || (depth0 != null ? depth0.id : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"id","hash":{},"data":data}) : helper))) + + "\">\n <div class=\"authorRow" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isUserAuthor : depth0),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isGuest : depth0),{"name":"if","hash":{},"fn":container.program(7, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\">\n" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isNotSystemMessage : depth0),{"name":"if","hash":{},"fn":container.program(9, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " <div class=\"date has-tooltip" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.relativeDate : depth0),{"name":"if","hash":{},"fn":container.program(12, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\" data-timestamp=\"" + + alias4(((helper = (helper = helpers.timestamp || (depth0 != null ? depth0.timestamp : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"timestamp","hash":{},"data":data}) : helper))) + + "\" title=\"" + + alias4(((helper = (helper = helpers.altDate || (depth0 != null ? depth0.altDate : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"altDate","hash":{},"data":data}) : helper))) + + "\">" + + alias4(((helper = (helper = helpers.date || (depth0 != null ? depth0.date : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"date","hash":{},"data":data}) : helper))) + + "</div>\n </div>\n <div class=\"message\">" + + ((stack1 = ((helper = (helper = helpers.formattedMessage || (depth0 != null ? depth0.formattedMessage : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"formattedMessage","hash":{},"data":data}) : helper))) != null ? stack1 : "") + + "</div>\n</li>\n"; +},"useData":true}); +})();
\ No newline at end of file diff --git a/js/views/templates/chatview.handlebars b/js/views/templates/chatview.handlebars new file mode 100644 index 000000000..a21321214 --- /dev/null +++ b/js/views/templates/chatview.handlebars @@ -0,0 +1,6 @@ +<ul class="comments"></ul> +<div class="emptycontent"> + <div class="icon-comment"></div> + <p>{{emptyResultLabel}}</p> +</div> +<div class="loading hidden" style="height: 50px"></div> diff --git a/js/views/templates/chatview_add_comment.handlebars b/js/views/templates/chatview_add_comment.handlebars new file mode 100644 index 000000000..4af7ad0a8 --- /dev/null +++ b/js/views/templates/chatview_add_comment.handlebars @@ -0,0 +1,19 @@ +<div class="newCommentRow comment"> + <div class="authorRow currentUser"> + <div class="avatar" data-user-id="{{actorId}}"></div> + {{#if actorId}} + <div class="author">{{actorDisplayName}}</div> + {{else}} + <div class="guest-name"></div> + {{/if}} + </div> + <form class="newCommentForm"> + <div contentEditable="true" class="message" data-placeholder="{{newMessagePlaceholder}}">{{message}}</div> + <input class="submit icon-confirm has-tooltip" type="submit" value="" title="{{submitText}}"/> + <div class="submitLoading icon-loading-small hidden"></div> + {{#if actorId}} + <button class="share icon-add has-tooltip" title="{{shareText}}"></button> + <div class="shareLoading icon-loading-small hidden"></div> + {{/if}} + </form> +</div> diff --git a/js/views/templates/chatview_comment.handlebars b/js/views/templates/chatview_comment.handlebars new file mode 100644 index 000000000..ef9d345b9 --- /dev/null +++ b/js/views/templates/chatview_comment.handlebars @@ -0,0 +1,10 @@ +<li class="comment{{#if isNotSystemMessage}}{{else}} systemMessage{{/if}}" data-id="{{id}}"> + <div class="authorRow{{#if isUserAuthor}} currentUser{{/if}}{{#if isGuest}} guestUser{{/if}}"> + {{#if isNotSystemMessage}} + <div class="avatar" data-user-id="{{#if isGuest}}{{else}}{{actorId}}{{/if}}" data-user-display-name="{{actorDisplayName}}"></div> + <div class="author">{{actorDisplayName}}</div> + {{/if}} + <div class="date has-tooltip{{#if relativeDate}} live-relative-timestamp{{/if}}" data-timestamp="{{timestamp}}" title="{{altDate}}">{{date}}</div> + </div> + <div class="message">{{{formattedMessage}}}</div> +</li> diff --git a/lib/PublicShareAuth/TemplateLoader.php b/lib/PublicShareAuth/TemplateLoader.php index 52f4d0ddd..2052f3195 100644 --- a/lib/PublicShareAuth/TemplateLoader.php +++ b/lib/PublicShareAuth/TemplateLoader.php @@ -97,6 +97,7 @@ class TemplateLoader { Util::addScript('spreed', 'views/roomlistview'); Util::addScript('spreed', 'views/sidebarview'); Util::addScript('spreed', 'views/tabview'); + Util::addScript('spreed', 'views/templates'); Util::addScript('spreed', 'views/virtuallist'); Util::addScript('spreed', 'richobjectstringparser'); Util::addScript('spreed', 'simplewebrtc'); diff --git a/templates/index-public.php b/templates/index-public.php index f85a7326f..799b54bd8 100644 --- a/templates/index-public.php +++ b/templates/index-public.php @@ -32,6 +32,7 @@ script( 'views/roomlistview', 'views/sidebarview', 'views/tabview', + 'views/templates', 'views/virtuallist', 'richobjectstringparser', 'simplewebrtc', diff --git a/templates/index.php b/templates/index.php index 0263073cd..a3dbb5290 100644 --- a/templates/index.php +++ b/templates/index.php @@ -31,6 +31,7 @@ script( 'views/roomlistview', 'views/sidebarview', 'views/tabview', + 'views/templates', 'views/virtuallist', 'richobjectstringparser', 'simplewebrtc', |