広場投稿追加画面の刷新 (#399) #413

マージ済み
みてるぞ が 103 個のコミットを feature/399 から main へマージ 2026-07-19 00:03:11 +09:00
4個のファイルの変更27行の追加26行の削除
コミット 040cc3f25d の変更だけを表示してゐます - すべてのコミットを表示
+6 -8
ファイルの表示
@@ -18,14 +18,12 @@ class PreviewController < ApplicationController
def thumbnail
return render_bad_request('URL は必須です.') if params[:url].blank?
image = MiniMagick::Image.read(Preview::ThumbnailFetcher.fetch(params[:url]))
image.auto_orient
image.resize '180x180>'
image.format 'png'
width, height = image.dimensions
raise Preview::ThumbnailFetcher::GenerationFailed, 'サムネール画像の変換に失敗しました.' if width > 180 || height > 180
send_data image.to_blob, type: 'image/png', disposition: 'inline'
attachment =
Post.resized_thumbnail_attachment(
StringIO.new(Preview::ThumbnailFetcher.fetch(params[:url])))
send_data attachment[:io].read,
type: attachment[:content_type],
disposition: 'inline'
rescue Preview::UrlSafety::UnsafeUrl => e
render_bad_request(e.message)
rescue Preview::HttpFetcher::FetchTimeout => e
-2
ファイルの表示
@@ -17,8 +17,6 @@ class Post < ApplicationRecord
MAX_SVG_DIMENSION = 4_096
MAX_SVG_PIXELS = 16_777_216
THUMBNAIL_PROCESS_TIMEOUT = 5.seconds
RASTER_THUMBNAIL_FORMATS = ['jpeg', 'png', 'gif', 'webp'].freeze
def self.resized_thumbnail_attachment(upload, content_type: nil)
upload.rewind
bytes = upload.read
+1 -11
ファイルの表示
@@ -4,10 +4,6 @@ module Preview
RASTER_IMAGE_CONTENT_TYPES = [
'image/jpeg', 'image/png', 'image/gif', 'image/webp'
].freeze
REMOTE_IMAGE_CONTENT_TYPES = [
*RASTER_IMAGE_CONTENT_TYPES,
'image/svg+xml'
].freeze
HTML_MAX_BYTES = 1.megabyte
NICONICO_XML_MAX_BYTES = 256.kilobytes
@@ -100,13 +96,7 @@ module Preview
nil
end
def self.allowed_remote_image_content_type?(content_type)
mime_type = content_type.to_s.split(';', 2).first.downcase.strip
REMOTE_IMAGE_CONTENT_TYPES.include?(mime_type)
end
private_class_method :fetch_image_or_nil, :fetch_image!,
:niconico_thumbnail_url,
:allowed_remote_image_content_type?
:niconico_thumbnail_url
end
end
+20 -5
ファイルの表示
@@ -110,6 +110,7 @@ const isRepairRow = (row: PostImportRow): boolean =>
&& hasErrorMessages (row.validationErrors)))
const DUPLICATE_URL_MESSAGE = 'URL が重複しています.'
const BULK_PROCESSING_FAILED_MESSAGE = '登録中にエラーが発生しました.'
const rowMetadataPending = (row: PostImportRow): boolean =>
row.status === 'pending'
@@ -314,14 +315,28 @@ const indexedBulkResults = (
}
if (result?.status === 'skipped')
{
const existingPostId =
result.existingPostId
?? result.existingPost?.id
?? row.existingPostId
if (existingPostId == null)
{
return {
sourceRow: row.sourceRow,
status: 'failed',
fieldWarnings: result.fieldWarnings,
baseWarnings: result.baseWarnings,
errors: {
...(errors ?? { }),
base: [...new Set ([...(errors?.base ?? []),
BULK_PROCESSING_FAILED_MESSAGE])],
},
recoverable: false }
}
return {
sourceRow: row.sourceRow,
status: 'skipped',
existingPostId:
result.existingPostId
?? result.existingPost?.id
?? row.existingPostId
?? row.sourceRow,
existingPostId,
existingPost: result.existingPost,
fieldWarnings: result.fieldWarnings,
baseWarnings: result.baseWarnings,