mirror of
https://github.com/discourse/discourse.git
synced 2025-05-22 07:53:49 +08:00
allow users to specify thumbnail size
This commit is contained in:
@ -115,6 +115,15 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, {
|
|||||||
var $replyControl = $('#reply-control');
|
var $replyControl = $('#reply-control');
|
||||||
$replyControl.DivResizer({ resize: this.resize, onDrag: this.movePanels });
|
$replyControl.DivResizer({ resize: this.resize, onDrag: this.movePanels });
|
||||||
Discourse.TransitionHelper.after($replyControl, this.resize);
|
Discourse.TransitionHelper.after($replyControl, this.resize);
|
||||||
|
this.ensureMaximumDimensionForImagesInPreview();
|
||||||
|
},
|
||||||
|
|
||||||
|
ensureMaximumDimensionForImagesInPreview: function() {
|
||||||
|
$('<style>#wmd-preview img, .cooked img {' +
|
||||||
|
'max-width:' + Discourse.SiteSettings.max_image_width + 'px;' +
|
||||||
|
'max-height:' + Discourse.SiteSettings.max_image_height + 'px;' +
|
||||||
|
'}</style>'
|
||||||
|
).appendTo('head');
|
||||||
},
|
},
|
||||||
|
|
||||||
click: function() {
|
click: function() {
|
||||||
|
@ -292,9 +292,6 @@
|
|||||||
}
|
}
|
||||||
#wmd-input, #wmd-preview {
|
#wmd-input, #wmd-preview {
|
||||||
color: $black;
|
color: $black;
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
video {
|
video {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
@ -245,9 +245,6 @@ display: none;
|
|||||||
}
|
}
|
||||||
#wmd-input, #wmd-preview {
|
#wmd-input, #wmd-preview {
|
||||||
color: $black;
|
color: $black;
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
video {
|
video {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
@ -455,7 +452,7 @@ div.ac-wrap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.control-row.reply-area {
|
.control-row.reply-area {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 1550px) {
|
@media screen and (min-width: 1550px) {
|
||||||
|
@ -229,7 +229,6 @@ class PostsController < ApplicationController
|
|||||||
:category,
|
:category,
|
||||||
:target_usernames,
|
:target_usernames,
|
||||||
:reply_to_post_number,
|
:reply_to_post_number,
|
||||||
:image_sizes,
|
|
||||||
:auto_close_days,
|
:auto_close_days,
|
||||||
:auto_track
|
:auto_track
|
||||||
]
|
]
|
||||||
@ -245,6 +244,7 @@ class PostsController < ApplicationController
|
|||||||
|
|
||||||
params.require(:raw)
|
params.require(:raw)
|
||||||
params.permit(*permitted).tap do |whitelisted|
|
params.permit(*permitted).tap do |whitelisted|
|
||||||
|
whitelisted[:image_sizes] = params[:image_sizes]
|
||||||
# TODO this does not feel right, we should name what meta_data is allowed
|
# TODO this does not feel right, we should name what meta_data is allowed
|
||||||
whitelisted[:meta_data] = params[:meta_data]
|
whitelisted[:meta_data] = params[:meta_data]
|
||||||
end
|
end
|
||||||
|
@ -19,7 +19,7 @@ class OptimizedImage < ActiveRecord::Base
|
|||||||
temp_file = Tempfile.new(["discourse-thumbnail", File.extname(original_path)])
|
temp_file = Tempfile.new(["discourse-thumbnail", File.extname(original_path)])
|
||||||
temp_path = temp_file.path
|
temp_path = temp_file.path
|
||||||
|
|
||||||
if ImageSorcery.new("#{original_path}[0]").convert(temp_path, resize: "#{width}x#{height}")
|
if ImageSorcery.new("#{original_path}[0]").convert(temp_path, resize: "#{width}x#{height}!")
|
||||||
thumbnail = OptimizedImage.create!(
|
thumbnail = OptimizedImage.create!(
|
||||||
upload_id: upload.id,
|
upload_id: upload.id,
|
||||||
sha1: Digest::SHA1.file(temp_path).hexdigest,
|
sha1: Digest::SHA1.file(temp_path).hexdigest,
|
||||||
|
@ -78,8 +78,8 @@ class SiteSetting < ActiveRecord::Base
|
|||||||
setting(:use_ssl, false)
|
setting(:use_ssl, false)
|
||||||
setting(:queue_jobs, !Rails.env.test?)
|
setting(:queue_jobs, !Rails.env.test?)
|
||||||
setting(:crawl_images, !Rails.env.test?)
|
setting(:crawl_images, !Rails.env.test?)
|
||||||
setting(:max_image_width, 690)
|
client_setting(:max_image_width, 690)
|
||||||
setting(:max_image_height, 500)
|
client_setting(:max_image_height, 500)
|
||||||
setting(:create_thumbnails, true)
|
setting(:create_thumbnails, true)
|
||||||
client_setting(:category_featured_topics, 6)
|
client_setting(:category_featured_topics, 6)
|
||||||
setting(:topics_per_page, 30)
|
setting(:topics_per_page, 30)
|
||||||
|
@ -14,19 +14,26 @@ class Upload < ActiveRecord::Base
|
|||||||
validates_presence_of :filesize
|
validates_presence_of :filesize
|
||||||
validates_presence_of :original_filename
|
validates_presence_of :original_filename
|
||||||
|
|
||||||
def thumbnail
|
def thumbnail(width = nil, height = nil)
|
||||||
|
width ||= self.width
|
||||||
|
height ||= self.height
|
||||||
optimized_images.where(width: width, height: height).first
|
optimized_images.where(width: width, height: height).first
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_thumbnail?
|
def has_thumbnail?(width = nil, height = nil)
|
||||||
thumbnail.present?
|
thumbnail(width, height).present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_thumbnail!
|
def create_thumbnail!(width, height)
|
||||||
return unless SiteSetting.create_thumbnails?
|
return unless SiteSetting.create_thumbnails?
|
||||||
return if has_thumbnail?
|
return if has_thumbnail?(width, height)
|
||||||
thumbnail = OptimizedImage.create_for(self, width, height)
|
thumbnail = OptimizedImage.create_for(self, width, height)
|
||||||
optimized_images << thumbnail if thumbnail
|
if thumbnail
|
||||||
|
optimized_images << thumbnail
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
save!
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
@ -85,15 +85,14 @@ class CookedPostProcessor
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update_dimensions!(img)
|
def update_dimensions!(img)
|
||||||
return if img['width'].present? && img['height'].present?
|
w, h = get_size_from_image_sizes(img['src'], @opts[:image_sizes]) || get_size(img['src'])
|
||||||
|
# make sure we limit the size of the thumbnail
|
||||||
w, h = get_size_from_image_sizes(img['src'], @opts[:image_sizes]) || image_dimensions(img['src'])
|
w, h = ImageSizer.resize(w, h)
|
||||||
|
# check whether the dimensions have changed
|
||||||
if w && h
|
@dirty = (img['width'].to_i != w) || (img['height'].to_i != h)
|
||||||
img['width'] = w
|
# update the dimensions
|
||||||
img['height'] = h
|
img['width'] = w
|
||||||
@dirty = true
|
img['height'] = h
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def associate_to_post(upload)
|
def associate_to_post(upload)
|
||||||
@ -123,7 +122,7 @@ class CookedPostProcessor
|
|||||||
|
|
||||||
if upload
|
if upload
|
||||||
# create a thumbnail
|
# create a thumbnail
|
||||||
upload.create_thumbnail!
|
upload.create_thumbnail!(width, height)
|
||||||
# optimize image
|
# optimize image
|
||||||
# TODO: optimize_image!(img)
|
# TODO: optimize_image!(img)
|
||||||
end
|
end
|
||||||
@ -156,7 +155,9 @@ class CookedPostProcessor
|
|||||||
a.add_child(img)
|
a.add_child(img)
|
||||||
|
|
||||||
# replace the image by its thumbnail
|
# replace the image by its thumbnail
|
||||||
img['src'] = relative_to_absolute(upload.thumbnail.url) if upload && upload.has_thumbnail?
|
w = img["width"]
|
||||||
|
h = img["height"]
|
||||||
|
img['src'] = relative_to_absolute(upload.thumbnail(w, h).url) if upload && upload.has_thumbnail?(w, h)
|
||||||
|
|
||||||
# then, some overlay informations
|
# then, some overlay informations
|
||||||
meta = Nokogiri::XML::Node.new("div", @doc)
|
meta = Nokogiri::XML::Node.new("div", @doc)
|
||||||
@ -193,23 +194,13 @@ class CookedPostProcessor
|
|||||||
end
|
end
|
||||||
|
|
||||||
def get_size_from_image_sizes(src, image_sizes)
|
def get_size_from_image_sizes(src, image_sizes)
|
||||||
if image_sizes.present?
|
[image_sizes[src]["width"], image_sizes[src]["height"]] if image_sizes.present? && image_sizes[src].present?
|
||||||
if dim = image_sizes[src]
|
|
||||||
ImageSizer.resize(dim['width'], dim['height'])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Retrieve the image dimensions for a url
|
|
||||||
def image_dimensions(url)
|
|
||||||
w, h = get_size(url)
|
|
||||||
ImageSizer.resize(w, h) if w && h
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_size(url)
|
def get_size(url)
|
||||||
uri = url
|
uri = url
|
||||||
# make sure urls have a scheme (otherwise, FastImage will fail)
|
# make sure urls have a scheme (otherwise, FastImage will fail)
|
||||||
uri = (SiteSetting.use_ssl? ? "https:" : "http:") + url if url.start_with?("//")
|
uri = (SiteSetting.use_ssl? ? "https:" : "http:") + url if url && url.start_with?("//")
|
||||||
return unless is_valid_image_uri?(uri)
|
return unless is_valid_image_uri?(uri)
|
||||||
# we can *always* crawl our own images
|
# we can *always* crawl our own images
|
||||||
return unless SiteSetting.crawl_images? || Discourse.store.has_been_uploaded?(url)
|
return unless SiteSetting.crawl_images? || Discourse.store.has_been_uploaded?(url)
|
||||||
|
@ -89,11 +89,6 @@ describe CookedPostProcessor do
|
|||||||
|
|
||||||
before { FastImage.stubs(:size).returns([150, 250]) }
|
before { FastImage.stubs(:size).returns([150, 250]) }
|
||||||
|
|
||||||
it "doesn't call image_dimensions because it knows the size" do
|
|
||||||
cpp.expects(:image_dimensions).never
|
|
||||||
cpp.post_process_images
|
|
||||||
end
|
|
||||||
|
|
||||||
it "adds the width from the image sizes provided" do
|
it "adds the width from the image sizes provided" do
|
||||||
cpp.post_process_images
|
cpp.post_process_images
|
||||||
cpp.html.should =~ /width=\"111\"/
|
cpp.html.should =~ /width=\"111\"/
|
||||||
@ -136,7 +131,7 @@ describe CookedPostProcessor do
|
|||||||
|
|
||||||
it "generates overlay information" do
|
it "generates overlay information" do
|
||||||
cpp.post_process_images
|
cpp.post_process_images
|
||||||
cpp.html.should match_html '<div><a href="http://test.localhost/uploads/default/1/1234567890123456.jpg" class="lightbox"><img src="http://test.localhost/uploads/default/_optimized/da3/9a3/ee5e6b4b0d_100x200.jpg" width="690" height="1380"><div class="meta">
|
cpp.html.should match_html '<div><a href="http://test.localhost/uploads/default/1/1234567890123456.jpg" class="lightbox"><img src="http://test.localhost/uploads/default/_optimized/da3/9a3/ee5e6b4b0d_690x1380.jpg" width="690" height="1380"><div class="meta">
|
||||||
<span class="filename">uploaded.jpg</span><span class="informations">1000x2000 1.21 KB</span><span class="expand"></span>
|
<span class="filename">uploaded.jpg</span><span class="informations">1000x2000 1.21 KB</span><span class="expand"></span>
|
||||||
</div></a></div>'
|
</div></a></div>'
|
||||||
cpp.should be_dirty
|
cpp.should be_dirty
|
||||||
@ -202,24 +197,6 @@ describe CookedPostProcessor do
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context "image_dimensions" do
|
|
||||||
|
|
||||||
let(:post) { build(:post) }
|
|
||||||
let(:cpp) { CookedPostProcessor.new(post) }
|
|
||||||
|
|
||||||
it "calls the resizer" do
|
|
||||||
SiteSetting.stubs(:max_image_width).returns(200)
|
|
||||||
cpp.expects(:get_size).returns([1000, 2000])
|
|
||||||
cpp.image_dimensions("http://foo.bar/image.png").should == [200, 400]
|
|
||||||
end
|
|
||||||
|
|
||||||
it "doesn't call the resizer when there is no size" do
|
|
||||||
cpp.expects(:get_size).returns(nil)
|
|
||||||
cpp.image_dimensions("http://foo.bar/image.png").should == nil
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
context "get_size" do
|
context "get_size" do
|
||||||
|
|
||||||
let(:post) { build(:post) }
|
let(:post) { build(:post) }
|
||||||
|
@ -393,8 +393,8 @@ describe PostsController do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "passes image_sizes through" do
|
it "passes image_sizes through" do
|
||||||
PostCreator.expects(:new).with(user, has_entries('image_sizes' => 'test')).returns(post_creator)
|
PostCreator.expects(:new).with(user, has_entries('image_sizes' => {'width' => '100', 'height' => '200'})).returns(post_creator)
|
||||||
xhr :post, :create, {raw: 'hello', image_sizes: 'test'}
|
xhr :post, :create, {raw: 'hello', image_sizes: {width: '100', height: '200'}}
|
||||||
end
|
end
|
||||||
|
|
||||||
it "passes meta_data through" do
|
it "passes meta_data through" do
|
||||||
|
@ -43,14 +43,14 @@ describe Upload do
|
|||||||
it "does not create a thumbnail when disabled" do
|
it "does not create a thumbnail when disabled" do
|
||||||
SiteSetting.stubs(:create_thumbnails?).returns(false)
|
SiteSetting.stubs(:create_thumbnails?).returns(false)
|
||||||
OptimizedImage.expects(:create_for).never
|
OptimizedImage.expects(:create_for).never
|
||||||
upload.create_thumbnail!
|
upload.create_thumbnail!(100, 100)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not create another thumbnail" do
|
it "does not create another thumbnail" do
|
||||||
SiteSetting.expects(:create_thumbnails?).returns(true)
|
SiteSetting.expects(:create_thumbnails?).returns(true)
|
||||||
upload.expects(:has_thumbnail?).returns(true)
|
upload.expects(:has_thumbnail?).returns(true)
|
||||||
OptimizedImage.expects(:create_for).never
|
OptimizedImage.expects(:create_for).never
|
||||||
upload.create_thumbnail!
|
upload.create_thumbnail!(100, 100)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a thumbnail" do
|
it "creates a thumbnail" do
|
||||||
@ -59,7 +59,7 @@ describe Upload do
|
|||||||
SiteSetting.expects(:create_thumbnails?).returns(true)
|
SiteSetting.expects(:create_thumbnails?).returns(true)
|
||||||
upload.expects(:has_thumbnail?).returns(false)
|
upload.expects(:has_thumbnail?).returns(false)
|
||||||
OptimizedImage.expects(:create_for).returns(thumbnail)
|
OptimizedImage.expects(:create_for).returns(thumbnail)
|
||||||
upload.create_thumbnail!
|
upload.create_thumbnail!(100, 100)
|
||||||
upload.reload
|
upload.reload
|
||||||
upload.optimized_images.count.should == 1
|
upload.optimized_images.count.should == 1
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user