philomena/lib/philomena_web/views/image_view.ex

283 lines
8.3 KiB
Elixir
Raw Normal View History

2019-08-18 18:17:05 +02:00
defmodule PhilomenaWeb.ImageView do
use PhilomenaWeb, :view
alias Philomena.Tags.Tag
alias Philomena.Images.Thumbnailer
2019-11-30 23:40:53 +01:00
def show_vote_counts?(%{hide_vote_counts: true}), do: false
def show_vote_counts?(_user), do: true
2019-12-23 15:50:39 +01:00
def title_text(image) do
tags = Tag.display_order(image.tags) |> Enum.map_join(", ", & &1.name)
"Size: #{image.image_width}x#{image.image_height} | Tagged: #{tags}"
end
# this is a bit ridiculous
2019-12-01 18:11:00 +01:00
def render_intent(_conn, %{thumbnails_generated: false}, _size), do: :not_rendered
2020-01-11 05:20:19 +01:00
2019-12-01 18:11:00 +01:00
def render_intent(conn, image, size) do
2019-12-09 05:41:35 +01:00
uris = thumb_urls(image, can?(conn, :show, image))
2019-11-30 23:40:53 +01:00
vid? = image.image_mime_type == "video/webm"
gif? = image.image_mime_type == "image/gif"
2019-12-23 15:50:39 +01:00
alt = title_text(image)
2019-11-30 23:40:53 +01:00
2019-12-01 18:11:00 +01:00
hidpi? = conn.cookies["hidpi"] == "true"
webm? = conn.cookies["webm"] == "true"
2019-11-30 23:40:53 +01:00
use_gif? = vid? and not webm? and size in ~W(thumb thumb_small thumb_tiny)a
2019-12-01 18:11:00 +01:00
filtered? = filter_or_spoiler_hits?(conn, image)
2019-11-30 23:40:53 +01:00
cond do
2019-12-01 18:11:00 +01:00
filtered? and vid? ->
{:filtered_video, alt}
filtered? and not vid? ->
{:filtered_image, alt}
2019-11-30 23:40:53 +01:00
hidpi? and not (gif? or vid?) ->
{:hidpi, uris[size], uris[:medium], alt}
not vid? or use_gif? ->
{:image, String.replace(uris[size], ".webm", ".gif"), alt}
true ->
{:video, uris[size], String.replace(uris[size], ".webm", ".mp4"), alt}
end
end
2019-10-05 02:27:26 +02:00
def thumb_urls(image, show_hidden) do
Thumbnailer.thumbnail_versions()
|> Map.new(fn {name, {width, height}} ->
if image.image_width > width or image.image_height > height do
{name, thumb_url(image, show_hidden, name)}
else
{name, thumb_url(image, show_hidden, :full)}
end
end)
2019-12-09 05:41:35 +01:00
|> append_full_url(image, show_hidden)
2019-11-30 23:40:53 +01:00
|> append_gif_urls(image, show_hidden)
end
2019-12-09 05:41:35 +01:00
defp append_full_url(urls, %{hidden_from_users: false} = image, _show_hidden),
do: Map.put(urls, :full, pretty_url(image, true, false))
defp append_full_url(urls, %{hidden_from_users: true} = image, true),
do: Map.put(urls, :full, thumb_url(image, true, :full))
defp append_full_url(urls, _image, _show_hidden),
do: urls
2019-11-30 23:40:53 +01:00
defp append_gif_urls(urls, %{image_mime_type: "image/gif"} = image, show_hidden) do
full_url = thumb_url(image, show_hidden, :full)
Map.merge(
urls,
%{
webm: String.replace(full_url, ".gif", ".webm"),
mp4: String.replace(full_url, ".gif", ".mp4")
}
)
2019-10-05 02:27:26 +02:00
end
2020-01-11 05:20:19 +01:00
2019-11-30 23:40:53 +01:00
defp append_gif_urls(urls, _image, _show_hidden), do: urls
2019-10-05 02:27:26 +02:00
2019-08-18 18:17:05 +02:00
def thumb_url(image, show_hidden, name) do
2019-08-18 20:14:36 +02:00
%{year: year, month: month, day: day} = image.created_at
deleted = image.hidden_from_users
root = image_url_root()
2020-01-11 05:20:19 +01:00
2019-11-17 04:19:20 +01:00
format =
image.image_format
|> to_string()
2019-11-17 04:19:20 +01:00
|> String.downcase()
2019-12-23 01:10:25 +01:00
|> thumb_format(name, false)
2019-08-18 20:14:36 +02:00
id_fragment =
if deleted and show_hidden do
2019-11-27 06:51:20 +01:00
"#{image.id}-#{image.hidden_image_key}"
2019-08-18 20:14:36 +02:00
else
"#{image.id}"
end
"#{root}/#{year}/#{month}/#{day}/#{id_fragment}/#{name}.#{format}"
end
2019-11-27 06:51:20 +01:00
def pretty_url(image, short, download) do
2019-08-18 20:14:36 +02:00
%{year: year, month: month, day: day} = image.created_at
root = image_url_root()
view = if download, do: "download", else: "view"
filename = if short, do: image.id, else: verbose_file_name(image)
2020-01-11 05:20:19 +01:00
2019-11-17 04:19:20 +01:00
format =
image.image_format
|> to_string()
2019-11-17 04:19:20 +01:00
|> String.downcase()
2019-12-23 01:10:25 +01:00
|> thumb_format(nil, download)
2019-08-18 20:14:36 +02:00
"#{root}/#{view}/#{year}/#{month}/#{day}/#{filename}.#{format}"
end
defp verbose_file_name(image) do
# Truncate filename to 150 characters, making room for the path + filename on Windows
# https://stackoverflow.com/questions/265769/maximum-filename-length-in-ntfs-windows-xp-and-windows-vista
file_name_slug_fragment =
image.tags
2021-02-11 01:40:19 +01:00
|> display_order()
|> Enum.map_join("_", & &1.slug)
|> String.to_charlist()
|> Enum.filter(&(&1 in ?a..?z or &1 in '0123456789_-+'))
|> List.to_string()
|> String.slice(0..150)
"#{image.id}__#{file_name_slug_fragment}"
2021-02-09 23:14:34 +01:00
end
2019-08-18 20:14:36 +02:00
def image_url_root do
Application.get_env(:philomena, :image_url_root)
2019-08-18 18:17:05 +02:00
end
2019-10-11 03:47:13 +02:00
2019-12-09 05:41:35 +01:00
def image_container_data(conn, image, size) do
2019-11-12 01:31:22 +01:00
[
2019-10-11 03:47:13 +02:00
image_id: image.id,
image_tags: Jason.encode!(Enum.map(image.tags, & &1.id)),
2020-12-06 16:08:13 +01:00
image_tag_aliases:
image.tags |> Enum.flat_map(&([&1] ++ &1.aliases)) |> Enum.map_join(", ", & &1.name),
tag_count: length(image.tags),
2019-10-11 03:47:13 +02:00
score: image.score,
faves: image.faves_count,
upvotes: image.upvotes_count,
downvotes: image.downvotes_count,
comment_count: image.comments_count,
created_at: DateTime.to_iso8601(image.created_at),
2019-10-11 03:47:13 +02:00
source_url: image.source_url,
2019-12-09 05:41:35 +01:00
uris: Jason.encode!(thumb_urls(image, can?(conn, :show, image))),
2019-10-11 03:47:13 +02:00
width: image.image_width,
height: image.image_height,
aspect_ratio: image.image_aspect_ratio,
size: size
]
2019-11-12 01:31:22 +01:00
end
2019-10-11 03:47:13 +02:00
2019-12-09 05:41:35 +01:00
def image_container(conn, image, size, block) do
2020-01-11 05:20:19 +01:00
content_tag(:div, block.(),
class: "image-container #{size}",
data: image_container_data(conn, image, size)
)
2019-10-11 03:47:13 +02:00
end
2019-11-12 00:54:20 +01:00
def display_order(tags) do
Tag.display_order(tags)
2019-11-12 00:54:20 +01:00
end
2019-11-17 04:19:20 +01:00
2019-12-17 19:53:41 +01:00
def username(%{name: name}), do: name
def username(_user), do: nil
def scope(conn), do: PhilomenaWeb.ImageScope.scope(conn)
2019-11-30 03:33:15 +01:00
def anonymous_by_default?(conn) do
conn.assigns.current_user.anonymous_by_default
end
2019-12-05 22:57:59 +01:00
def info_row(_conn, []), do: []
2020-01-11 05:20:19 +01:00
2019-12-05 23:01:09 +01:00
def info_row(conn, [{tag, description, dnp_entries}]) do
2020-01-11 05:20:19 +01:00
render(PhilomenaWeb.TagView, "_tag_info_row.html",
conn: conn,
tag: tag,
body: description,
dnp_entries: dnp_entries
)
2019-12-05 22:57:59 +01:00
end
2020-01-11 05:20:19 +01:00
2019-12-05 22:57:59 +01:00
def info_row(conn, tags) do
2020-01-11 05:20:19 +01:00
render(PhilomenaWeb.TagView, "_tags_row.html", conn: conn, tags: tags)
2019-12-05 22:57:59 +01:00
end
2019-12-16 23:11:16 +01:00
def quick_tag(conn) do
if can?(conn, :batch_update, Tag) do
2020-01-11 05:20:19 +01:00
render(PhilomenaWeb.ImageView, "_quick_tag.html", conn: conn)
2019-12-16 23:11:16 +01:00
end
end
2019-12-07 17:48:39 +01:00
def deleter(%{deleter: %{name: name}}), do: name
def deleter(_image), do: "System"
2021-09-27 03:54:47 +02:00
def scaled_value(%{scale_large_images: scale}), do: scale
2019-12-10 02:28:00 +01:00
def scaled_value(_user), do: "true"
def hides_images?(conn), do: can?(conn, :hide, %Philomena.Images.Image{})
2019-12-26 23:43:32 +01:00
def random_button(conn, params) do
2020-01-11 05:20:19 +01:00
render(PhilomenaWeb.ImageView, "_random_button.html", conn: conn, params: params)
2019-12-26 23:43:32 +01:00
end
def hidden_toggle(%{assigns: %{current_user: nil}}, _route, _params), do: nil
2020-01-11 05:20:19 +01:00
2019-12-18 01:44:26 +01:00
def hidden_toggle(conn, route, params) do
2020-01-11 05:20:19 +01:00
render(PhilomenaWeb.ImageView, "_hidden_toggle.html", route: route, params: params, conn: conn)
end
def deleted_toggle(conn, route, params) do
if hides_images?(conn) do
2020-01-11 05:20:19 +01:00
render(PhilomenaWeb.ImageView, "_deleted_toggle.html",
route: route,
params: params,
conn: conn
)
end
end
2019-12-23 01:10:25 +01:00
defp thumb_format("svg", _name, false), do: "png"
defp thumb_format(_, :rendered, _download), do: "png"
defp thumb_format(format, _name, _download), do: format
2019-12-01 18:11:00 +01:00
2020-06-07 03:03:17 +02:00
def image_filter_data(image) do
2019-12-01 18:11:00 +01:00
%{
2020-01-11 05:20:19 +01:00
id: image.id,
2020-12-06 16:08:13 +01:00
"namespaced_tags.name":
image.tags |> Enum.flat_map(&([&1] ++ &1.aliases)) |> Enum.map_join(", ", & &1.name),
tag_count: length(image.tags),
2020-01-11 05:20:19 +01:00
score: image.score,
faves: image.faves_count,
upvotes: image.upvotes_count,
downvotes: image.downvotes_count,
comment_count: image.comments_count,
created_at: image.created_at,
first_seen_at: image.first_seen_at,
source_url: image.source_url,
width: image.image_width,
height: image.image_height,
aspect_ratio: image.image_aspect_ratio,
sha512_hash: image.image_sha512_hash,
orig_sha512_hash: image.image_orig_sha512_hash
2019-12-01 18:11:00 +01:00
}
end
def filter_or_spoiler_hits?(conn, image) do
tag_filter_or_spoiler_hits?(conn, image) or complex_filter_or_spoiler_hits?(conn, image)
end
defp tag_filter_or_spoiler_hits?(conn, image) do
filter = conn.assigns.current_filter
filtered_tag_ids = MapSet.new(filter.spoilered_tag_ids ++ filter.hidden_tag_ids)
image_tag_ids = MapSet.new(image.tags, & &1.id)
MapSet.size(MapSet.intersection(filtered_tag_ids, image_tag_ids)) > 0
end
defp complex_filter_or_spoiler_hits?(conn, image) do
doc = image_filter_data(image)
complex_filter = conn.assigns.compiled_complex_filter
complex_spoiler = conn.assigns.compiled_complex_spoiler
2020-01-11 05:20:19 +01:00
2019-12-01 18:11:00 +01:00
query = %{
bool: %{
should: [complex_filter, complex_spoiler]
}
}
Philomena.Search.Evaluator.hits?(doc, query)
2019-12-01 18:11:00 +01:00
end
2019-08-18 18:17:05 +02:00
end