diff --git a/Gemfile_rails4.lock b/Gemfile_rails4.lock index 1f85f118fdb..2a459f1a0d2 100644 --- a/Gemfile_rails4.lock +++ b/Gemfile_rails4.lock @@ -89,6 +89,13 @@ GIT rake rake-compiler +GIT + remote: https://github.com/MiniProfiler/rack-mini-profiler.git + revision: e08b751091a41f0066a1b28bd4e2b9b3480a1c1b + specs: + rack-mini-profiler (0.1.31) + rack (>= 1.1.3) + GIT remote: https://github.com/SamSaffron/annotate_models.git revision: ebe4ba7e3f6ceeb43e4e40078da2b261a1bb71b2 @@ -146,12 +153,6 @@ GIT activerecord (>= 3.0.0) activesupport (>= 3.0.0) -PATH - remote: /Users/sam/Source/rack-mini-profiler - specs: - rack-mini-profiler (0.1.31) - rack (>= 1.1.3) - PATH remote: vendor/gems/discourse_emoji specs: diff --git a/app/assets/javascripts/admin/controllers/admin_email_index_controller.js b/app/assets/javascripts/admin/controllers/admin_email_index_controller.js index 673411d8ea2..8da9fa2d493 100644 --- a/app/assets/javascripts/admin/controllers/admin_email_index_controller.js +++ b/app/assets/javascripts/admin/controllers/admin_email_index_controller.js @@ -6,7 +6,7 @@ @namespace Discourse @module Discourse **/ -Discourse.AdminEmailIndexController = Discourse.Controller.extend(Discourse.Presence, { +Discourse.AdminEmailIndexController = Discourse.Controller.extend({ /** Is the "send test email" button disabled? diff --git a/app/assets/javascripts/admin/controllers/admin_email_preview_digest_controller.js b/app/assets/javascripts/admin/controllers/admin_email_preview_digest_controller.js index 39de14ae996..eb54d21c6fb 100644 --- a/app/assets/javascripts/admin/controllers/admin_email_preview_digest_controller.js +++ b/app/assets/javascripts/admin/controllers/admin_email_preview_digest_controller.js @@ -6,7 +6,7 @@ @namespace Discourse @module Discourse **/ -Discourse.AdminEmailPreviewDigestController = Discourse.ObjectController.extend(Discourse.Presence, { +Discourse.AdminEmailPreviewDigestController = Discourse.ObjectController.extend({ refresh: function() { var model = this.get('model'); diff --git a/app/assets/javascripts/discourse.js b/app/assets/javascripts/discourse.js index f71d9d104f6..558a06710c7 100644 --- a/app/assets/javascripts/discourse.js +++ b/app/assets/javascripts/discourse.js @@ -208,6 +208,17 @@ Discourse = Ember.Application.createWithMixins(Discourse.Ajax, { } }, + /** + Add an initializer hook for after the Discourse Application starts up. + + @method addInitializer + @param {Function} init the initializer to add. + **/ + addInitializer: function(init) { + Discourse.initializers = Discourse.initializers || []; + Discourse.initializers.push(init); + }, + /** Start up the Discourse application. @@ -223,6 +234,12 @@ Discourse = Ember.Application.createWithMixins(Discourse.Ajax, { // Developer specific functions Discourse.Development.observeLiveChanges(); Discourse.subscribeUserToNotifications(); + + if (Discourse.initializers) { + Discourse.initializers.forEach(function (init) { + init.call(this); + }); + } } }); diff --git a/app/assets/javascripts/discourse/views/composer/composer_view.js b/app/assets/javascripts/discourse/views/composer/composer_view.js index 49bc80801e4..19d05537461 100644 --- a/app/assets/javascripts/discourse/views/composer/composer_view.js +++ b/app/assets/javascripts/discourse/views/composer/composer_view.js @@ -8,7 +8,7 @@ @namespace Discourse @module Discourse **/ -Discourse.ComposerView = Discourse.View.extend({ +Discourse.ComposerView = Discourse.View.extend(Ember.Evented, { templateName: 'composer', elementId: 'reply-control', classNameBindings: ['model.creatingPrivateMessage:private-message', @@ -49,18 +49,17 @@ Discourse.ComposerView = Discourse.View.extend({ }.property('model.createdPost'), observeReplyChanges: function() { - var composerView = this; + var self = this; if (this.get('model.hidePreview')) return; - Ember.run.next(null, function() { - var $wmdPreview, caretPosition; - if (composerView.editor) { - composerView.editor.refreshPreview(); + Ember.run.next(function() { + if (self.editor) { + self.editor.refreshPreview(); // if the caret is on the last line ensure preview scrolled to bottom - caretPosition = Discourse.Utilities.caretPosition(composerView.wmdInput[0]); - if (!composerView.wmdInput.val().substring(caretPosition).match(/\n/)) { - $wmdPreview = $('#wmd-preview'); + var caretPosition = Discourse.Utilities.caretPosition(self.wmdInput[0]); + if (!self.wmdInput.val().substring(caretPosition).match(/\n/)) { + var $wmdPreview = $('#wmd-preview'); if ($wmdPreview.is(':visible')) { - return $wmdPreview.scrollTop($wmdPreview[0].scrollHeight); + $wmdPreview.scrollTop($wmdPreview[0].scrollHeight); } } } @@ -129,8 +128,8 @@ Discourse.ComposerView = Discourse.View.extend({ Discourse.SyntaxHighlighting.apply($wmdPreview); - var post = this.get('model.post'); - var refresh = false; + var post = this.get('model.post'), + refresh = false; // If we are editing a post, we'll refresh its contents once. This is a feature that // allows a user to refresh its contents once. @@ -146,6 +145,8 @@ Discourse.ComposerView = Discourse.View.extend({ $('span.mention', $wmdPreview).each(function(i, e) { Discourse.Mention.load(e, refresh); }); + + this.trigger('previewRefreshed', $wmdPreview); }, 100), initEditor: function() { diff --git a/app/assets/javascripts/discourse/views/post_view.js b/app/assets/javascripts/discourse/views/post_view.js index db155843ef9..57c3f5e548e 100644 --- a/app/assets/javascripts/discourse/views/post_view.js +++ b/app/assets/javascripts/discourse/views/post_view.js @@ -6,7 +6,7 @@ @namespace Discourse @module Discourse **/ -Discourse.PostView = Discourse.GroupedView.extend({ +Discourse.PostView = Discourse.GroupedView.extend(Ember.Evented, { classNames: ['topic-post', 'clearfix'], templateName: 'post', classNameBindings: ['postTypeClass', @@ -193,8 +193,9 @@ Discourse.PostView = Discourse.GroupedView.extend({ }, didInsertElement: function() { - var $post = this.$(); - var post = this.get('post'); + var $post = this.$(), + post = this.get('post'); + this.showLinkCounts(); // Track this post @@ -204,6 +205,8 @@ Discourse.PostView = Discourse.GroupedView.extend({ Discourse.SyntaxHighlighting.apply($post); Discourse.Lightbox.apply($post); + this.trigger('postViewInserted', $post); + // Find all the quotes this.insertQuoteControls(); diff --git a/app/assets/stylesheets/mobile/topic-post.css.scss b/app/assets/stylesheets/mobile/topic-post.css.scss index 6bf5c81f862..6e4cceaa732 100644 --- a/app/assets/stylesheets/mobile/topic-post.css.scss +++ b/app/assets/stylesheets/mobile/topic-post.css.scss @@ -31,6 +31,8 @@ span.badge-posts { } } + + button.create { float: right !important; border: 1px solid #888; @@ -449,6 +451,8 @@ blockquote { margin-left: 8px; color: #323232; font-family: "FontAwesome"; + position: relative; + z-index: 20; } .back:before { content: "\f062"; diff --git a/app/models/post.rb b/app/models/post.rb index eca7cee999f..fd892902f98 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -284,7 +284,8 @@ class Post < ActiveRecord::Base AND p2.user_id <> post_timings.user_id GROUP BY post_timings.topic_id, post_timings.post_number) AS x WHERE x.topic_id = posts.topic_id - AND x.post_number = posts.post_number") + AND x.post_number = posts.post_number + AND (posts.avg_time <> (x.gmean / 1000)::int OR posts.avg_time IS NULL)") end end diff --git a/config/locales/server.ru.yml b/config/locales/server.ru.yml index 27588458619..82c81477d81 100644 --- a/config/locales/server.ru.yml +++ b/config/locales/server.ru.yml @@ -778,7 +778,7 @@ ru: Если вам интересно, пройдите по ссылке ниже, чтобы попасть в обсуждение: - [Visit %{site_name}[1] + [Visit %{site_name}][1] Вы приглашены доверенным пользователем, поэтому сразу сможете разместить свой ответ без входа на сайт. diff --git a/lib/oneboxer/whitelist.rb b/lib/oneboxer/whitelist.rb index 1eb56c41e0d..392c788dfb5 100644 --- a/lib/oneboxer/whitelist.rb +++ b/lib/oneboxer/whitelist.rb @@ -87,6 +87,7 @@ module Oneboxer Entry.new(/^https?:\/\/(?:www\.)?screenr\.com\/.+/), Entry.new(/^https?:\/\/(?:www\.)?tumblr\.com\/.+/, false), Entry.new(/^https?:\/\/(?:www\.)?howtogeek\.com\/.+/, false), + Entry.new(/^https?:\/\/(?:www\.)?screencast\.com\/.+/), Entry.new(/\/\d{4}\/\d{2}\/\d{2}\//, false), # wordpress Entry.new(/^https?:\/\/[^\/]+\/t\/[^\/]+\/\d+(\/\d+)?(\?.*)?$/), diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb index ca74b9c658c..60b2f1fef78 100644 --- a/lib/plugin/instance.rb +++ b/lib/plugin/instance.rb @@ -47,6 +47,8 @@ class Plugin::Instance end def delete_extra_automatic_assets(good_paths) + return unless Dir.exists? auto_generated_path + filenames = good_paths.map{|f| File.basename(f)} # nuke old files Dir.foreach(auto_generated_path) do |p| @@ -102,7 +104,7 @@ class Plugin::Instance def automatic_assets css = "" - js = "(function(){" + js = "" css = @styles.join("\n") if @styles js = @javascripts.join("\n") if @javascripts @@ -127,10 +129,14 @@ class Plugin::Instance end end - js << "})();" + # Generate an IIFE for the JS + js = "(function(){#{js}})();" if js.present? - # TODO don't serve blank assets - [[css,"css"],[js,"js"]].map do |asset, extension| + result = [] + result << [css, 'css'] if css.present? + result << [js, 'js'] if js.present? + + result.map do |asset, extension| hash = Digest::SHA1.hexdigest asset ["#{auto_generated_path}/plugin_#{hash}.#{extension}", asset] end diff --git a/lib/topic_query.rb b/lib/topic_query.rb index 43c60315407..26b5a14ba94 100644 --- a/lib/topic_query.rb +++ b/lib/topic_query.rb @@ -176,7 +176,7 @@ class TopicQuery end def list_new_in_category(category) - create_list(:new_in_category) {|l| l.where(category_id: category.id).by_newest.first(25)} + create_list(:new_in_category, unordered: true) {|l| l.where(category_id: category.id).by_newest.first(25)} end def self.new_filter(list, treat_as_new_topic_start_date) diff --git a/spec/components/plugin/instance_spec.rb b/spec/components/plugin/instance_spec.rb index 6ad7c81f2ca..7f543b99086 100644 --- a/spec/components/plugin/instance_spec.rb +++ b/spec/components/plugin/instance_spec.rb @@ -34,7 +34,7 @@ describe Plugin::Instance do auth_provider.authenticator.name.should == 'ubuntu' # calls ensure_assets! make sure they are there - plugin.assets.count.should == 2 + plugin.assets.count.should == 1 plugin.assets.each do |a| File.exists?(a).should be_true end diff --git a/test/javascripts/controllers/admin_email_index_controller_test.js b/test/javascripts/controllers/admin_email_index_controller_test.js new file mode 100644 index 00000000000..a5330b3186c --- /dev/null +++ b/test/javascripts/controllers/admin_email_index_controller_test.js @@ -0,0 +1,5 @@ +module("Discourse.AdminEmailIndexController"); + +test("mixes in Discourse.Presence", function() { + ok(Discourse.Presence.detect(Discourse.AdminEmailIndexController.create())); +}); diff --git a/test/javascripts/controllers/admin_email_preview_digest_controller_test.js b/test/javascripts/controllers/admin_email_preview_digest_controller_test.js new file mode 100644 index 00000000000..606caba5ad9 --- /dev/null +++ b/test/javascripts/controllers/admin_email_preview_digest_controller_test.js @@ -0,0 +1,5 @@ +module("Discourse.AdminEmailPreviewDigestController"); + +test("mixes in Discourse.Presence", function() { + ok(Discourse.Presence.detect(Discourse.AdminEmailPreviewDigestController.create())); +});