From 6329b01e38be0c8a427e89415e59a9194f7accd4 Mon Sep 17 00:00:00 2001 From: "byte[]" Date: Fri, 6 Dec 2019 12:12:55 -0500 Subject: [PATCH] hide/spoiler/watch from tag dropdown --- lib/philomena/filters.ex | 32 +++++++++++ lib/philomena/filters/filter.ex | 8 +++ lib/philomena/users.ex | 16 ++++++ lib/philomena/users/user.ex | 4 ++ .../controllers/filter/hide_controller.ex | 56 +++++++++++++++++++ .../controllers/filter/spoiler_controller.ex | 56 +++++++++++++++++++ .../controllers/tag/watch_controller.ex | 43 ++++++++++++++ lib/philomena_web/router.ex | 6 ++ .../templates/filter/_form.html.slime | 3 + .../templates/filter/show.html.slime | 5 +- .../templates/image/_image_page.html.slime | 2 +- .../templates/image/_image_target.html.slime | 3 +- .../templates/profile/show.html.slime | 2 +- .../templates/search/reverse/index.html.slime | 2 +- .../templates/tag/_tag.html.slime | 12 ++-- .../templates/tag/_tag_info_row.html.slime | 2 +- .../templates/tag/_tag_list.html.slime | 2 +- .../templates/tag/index.html.slime | 2 +- .../templates/user_link/show.html.slime | 2 +- 19 files changed, 241 insertions(+), 17 deletions(-) create mode 100644 lib/philomena_web/controllers/filter/hide_controller.ex create mode 100644 lib/philomena_web/controllers/filter/spoiler_controller.ex create mode 100644 lib/philomena_web/controllers/tag/watch_controller.ex diff --git a/lib/philomena/filters.ex b/lib/philomena/filters.ex index 70affae8..7f81ef7c 100644 --- a/lib/philomena/filters.ex +++ b/lib/philomena/filters.ex @@ -142,4 +142,36 @@ defmodule Philomena.Filters do end ) end + + def hide_tag(filter, tag) do + hidden_tag_ids = Enum.uniq([tag.id | filter.hidden_tag_ids]) + + filter + |> Filter.hidden_tags_changeset(hidden_tag_ids) + |> Repo.update() + end + + def unhide_tag(filter, tag) do + hidden_tag_ids = filter.hidden_tag_ids -- [tag.id] + + filter + |> Filter.hidden_tags_changeset(hidden_tag_ids) + |> Repo.update() + end + + def spoiler_tag(filter, tag) do + spoilered_tag_ids = Enum.uniq([tag.id | filter.spoilered_tag_ids]) + + filter + |> Filter.spoilered_tags_changeset(spoilered_tag_ids) + |> Repo.update() + end + + def unspoiler_tag(filter, tag) do + spoilered_tag_ids = filter.spoilered_tag_ids -- [tag.id] + + filter + |> Filter.spoilered_tags_changeset(spoilered_tag_ids) + |> Repo.update() + end end diff --git a/lib/philomena/filters/filter.ex b/lib/philomena/filters/filter.ex index d14f991e..70bcc8fc 100644 --- a/lib/philomena/filters/filter.ex +++ b/lib/philomena/filters/filter.ex @@ -45,6 +45,14 @@ defmodule Philomena.Filters.Filter do |> unsafe_validate_unique([:user_id, :name], Repo) end + def hidden_tags_changeset(filter, hidden_tag_ids) do + change(filter, hidden_tag_ids: hidden_tag_ids) + end + + def spoilered_tags_changeset(filter, spoilered_tag_ids) do + change(filter, spoilered_tag_ids: spoilered_tag_ids) + end + defp validate_my_downvotes(changeset, field) do value = get_field(changeset, field) || "" diff --git a/lib/philomena/users.ex b/lib/philomena/users.ex index 64e065f8..4498ae6c 100644 --- a/lib/philomena/users.ex +++ b/lib/philomena/users.ex @@ -95,6 +95,22 @@ defmodule Philomena.Users do |> Repo.update() end + def watch_tag(%User{} = user, tag) do + watched_tag_ids = Enum.uniq([tag.id | user.watched_tag_ids]) + + user + |> User.watched_tags_changeset(watched_tag_ids) + |> Repo.update() + end + + def unwatch_tag(%User{} = user, tag) do + watched_tag_ids = user.watched_tag_ids -- [tag.id] + + user + |> User.watched_tags_changeset(watched_tag_ids) + |> Repo.update() + end + @doc """ Returns an `%Ecto.Changeset{}` for tracking user changes. diff --git a/lib/philomena/users/user.ex b/lib/philomena/users/user.ex index a2b82a07..7be31121 100644 --- a/lib/philomena/users/user.ex +++ b/lib/philomena/users/user.ex @@ -193,6 +193,10 @@ defmodule Philomena.Users.User do |> validate_format(:personal_title, ~r/\A((?!site|admin|moderator|assistant|developer|\p{C}).)*\z/iu) end + def watched_tags_changeset(user, watched_tag_ids) do + change(user, watched_tag_ids: watched_tag_ids) + end + def create_totp_secret_changeset(user) do secret = :crypto.strong_rand_bytes(15) |> Base.encode32() data = Philomena.Users.Encryptor.encrypt_model(secret) diff --git a/lib/philomena_web/controllers/filter/hide_controller.ex b/lib/philomena_web/controllers/filter/hide_controller.ex new file mode 100644 index 00000000..b76637ce --- /dev/null +++ b/lib/philomena_web/controllers/filter/hide_controller.ex @@ -0,0 +1,56 @@ +defmodule PhilomenaWeb.Filter.HideController do + use PhilomenaWeb, :controller + + alias Philomena.Filters + alias Philomena.Tags.Tag + alias Philomena.Repo + + plug :authorize_filter + plug :load_tag + + def create(conn, _params) do + case Filters.hide_tag(conn.assigns.current_filter, conn.assigns.tag) do + {:ok, _filter} -> + conn + |> put_status(:ok) + |> text("") + + {:error, _changeset} -> + conn + |> put_status(:internal_server_error) + |> text("") + end + end + + def delete(conn, _params) do + case Filters.unhide_tag(conn.assigns.current_filter, conn.assigns.tag) do + {:ok, _filter} -> + conn + |> put_status(:ok) + |> text("") + + {:error, _changeset} -> + conn + |> put_status(:internal_server_error) + |> text("") + end + end + + defp authorize_filter(conn, _opts) do + case Canada.Can.can?(conn.assigns.current_user, :edit, conn.assigns.current_filter) do + true -> + conn + + false -> + conn + |> put_status(:forbidden) + |> text("") + end + end + + def load_tag(conn, _opts) do + tag = Repo.get_by!(Tag, slug: URI.encode(conn.params["tag"])) + + assign(conn, :tag, tag) + end +end \ No newline at end of file diff --git a/lib/philomena_web/controllers/filter/spoiler_controller.ex b/lib/philomena_web/controllers/filter/spoiler_controller.ex new file mode 100644 index 00000000..e9ba0fe7 --- /dev/null +++ b/lib/philomena_web/controllers/filter/spoiler_controller.ex @@ -0,0 +1,56 @@ +defmodule PhilomenaWeb.Filter.SpoilerController do + use PhilomenaWeb, :controller + + alias Philomena.Filters + alias Philomena.Tags.Tag + alias Philomena.Repo + + plug :authorize_filter + plug :load_tag + + def create(conn, _params) do + case Filters.spoiler_tag(conn.assigns.current_filter, conn.assigns.tag) do + {:ok, _filter} -> + conn + |> put_status(:ok) + |> text("") + + {:error, _changeset} -> + conn + |> put_status(:internal_server_error) + |> text("") + end + end + + def delete(conn, _params) do + case Filters.unspoiler_tag(conn.assigns.current_filter, conn.assigns.tag) do + {:ok, _filter} -> + conn + |> put_status(:ok) + |> text("") + + {:error, _changeset} -> + conn + |> put_status(:internal_server_error) + |> text("") + end + end + + defp authorize_filter(conn, _opts) do + case Canada.Can.can?(conn.assigns.current_user, :edit, conn.assigns.current_filter) do + true -> + conn + + false -> + conn + |> put_status(:forbidden) + |> text("") + end + end + + def load_tag(conn, _opts) do + tag = Repo.get_by!(Tag, slug: URI.encode(conn.params["tag"])) + + assign(conn, :tag, tag) + end +end \ No newline at end of file diff --git a/lib/philomena_web/controllers/tag/watch_controller.ex b/lib/philomena_web/controllers/tag/watch_controller.ex new file mode 100644 index 00000000..8a588faa --- /dev/null +++ b/lib/philomena_web/controllers/tag/watch_controller.ex @@ -0,0 +1,43 @@ +defmodule PhilomenaWeb.Tag.WatchController do + use PhilomenaWeb, :controller + + alias Philomena.Tags.Tag + alias Philomena.Users + alias Philomena.Repo + + plug :load_tag + + def create(conn, _params) do + case Users.watch_tag(conn.assigns.current_user, conn.assigns.tag) do + {:ok, _user} -> + conn + |> put_status(:ok) + |> text("") + + {:error, _changeset} -> + conn + |> put_status(:internal_server_error) + |> text("") + end + end + + def delete(conn, _params) do + case Users.unwatch_tag(conn.assigns.current_user, conn.assigns.tag) do + {:ok, _user} -> + conn + |> put_status(:ok) + |> text("") + + {:error, _changeset} -> + conn + |> put_status(:internal_server_error) + |> text("") + end + end + + def load_tag(conn, _opts) do + tag = Repo.get_by!(Tag, slug: URI.encode(conn.params["tag_id"])) + + assign(conn, :tag, tag) + end +end \ No newline at end of file diff --git a/lib/philomena_web/router.ex b/lib/philomena_web/router.ex index 0b4aca0b..725610e0 100644 --- a/lib/philomena_web/router.ex +++ b/lib/philomena_web/router.ex @@ -124,6 +124,12 @@ defmodule PhilomenaWeb.Router do scope "/filters", Filter, as: :filter do resources "/spoiler_type", SpoilerTypeController, only: [:update], singleton: true + resources "/hide", HideController, only: [:create, :delete], singleton: true + resources "/spoiler", SpoilerController, only: [:create, :delete], singleton: true + end + + resources "/tags", TagController, only: [] do + resources "/watch", Tag.WatchController, only: [:create, :delete], singleton: true end resources "/reports", ReportController, only: [:index] diff --git a/lib/philomena_web/templates/filter/_form.html.slime b/lib/philomena_web/templates/filter/_form.html.slime index 9f9b4585..9d19bb34 100644 --- a/lib/philomena_web/templates/filter/_form.html.slime +++ b/lib/philomena_web/templates/filter/_form.html.slime @@ -11,6 +11,7 @@ ' This is a friendly name for this filter - it should be short and descriptive. .field = textarea f, :description, class: "input input--wide", placeholder: "Description" + = error_tag f, :description .fieldlabel ' Here you can describe your filter in a bit more detail. @@ -19,6 +20,7 @@ = label f, :spoilered_tag_list, "Spoilered Tags" br = render PhilomenaWeb.TagView, "_tag_editor.html", f: f, name: :spoilered_tag_list, type: "edit" + = error_tag f, :spoilered_tag_list .fieldlabel ' These tags will spoiler the images they're associated with. .field @@ -43,6 +45,7 @@ = label f, :hidden_tag_list, "Hidden Tags" br = render PhilomenaWeb.TagView, "_tag_editor.html", f: f, name: :hidden_tag_list, type: "edit" + = error_tag f, :hidden_tag_list .fieldlabel ' These tags will hide images entirely from the site; if you go directly to an image, it will spoiler it. .field diff --git a/lib/philomena_web/templates/filter/show.html.slime b/lib/philomena_web/templates/filter/show.html.slime index af755667..8ecd5f5a 100644 --- a/lib/philomena_web/templates/filter/show.html.slime +++ b/lib/philomena_web/templates/filter/show.html.slime @@ -31,7 +31,6 @@ h1 p.filter-maintainer ' This filter is maintained by = render PhilomenaWeb.UserAttributionView, "_user.html", object: @filter, conn: @conn - ' . p.filter-description = @filter.description @@ -40,7 +39,7 @@ h1 h5 This filter spoilers... = for tag <- @spoilered_tags do - = render PhilomenaWeb.TagView, "_tag.html", tag: tag + = render PhilomenaWeb.TagView, "_tag.html", tag: tag, conn: @conn pre.spoiler-filter-code = @filter.spoilered_complex_str @@ -52,7 +51,7 @@ h1 h5 This filter hides... = for tag <- @hidden_tags do - = render PhilomenaWeb.TagView, "_tag.html", tag: tag + = render PhilomenaWeb.TagView, "_tag.html", tag: tag, conn: @conn pre.spoiler-filter-code = @filter.hidden_complex_str diff --git a/lib/philomena_web/templates/image/_image_page.html.slime b/lib/philomena_web/templates/image/_image_page.html.slime index 2f353001..28c4344d 100644 --- a/lib/philomena_web/templates/image/_image_page.html.slime +++ b/lib/philomena_web/templates/image/_image_page.html.slime @@ -1,6 +1,6 @@ .center--layout--flex = if @image.thumbnails_generated do - = render PhilomenaWeb.ImageView, "_image_target.html", image: @image + = render PhilomenaWeb.ImageView, "_image_target.html", image: @image, conn: @conn - else #thumbnails-not-yet-generated.block.block--fixed.block--warning.layout--narrow h3 Just a moment diff --git a/lib/philomena_web/templates/image/_image_target.html.slime b/lib/philomena_web/templates/image/_image_target.html.slime index cc91aeb6..4c5ff9c5 100644 --- a/lib/philomena_web/templates/image/_image_target.html.slime +++ b/lib/philomena_web/templates/image/_image_target.html.slime @@ -5,7 +5,8 @@ p = img_tag(Routes.static_path(PhilomenaWeb.Endpoint, "/images/tagblocked.svg"), width: 250, height: 250, data: [click_unfilter: @image.id]) span.filter-explanation - =< link("your current filter", to: "#", class: "filter-link") + =< link("your current filter", to: Routes.filter_path(@conn, :show, @conn.assigns.current_filter), class: "filter-link") + ' . #image_target.hidden.image-show data-scaled="true" data-uris=Jason.encode!(thumb_urls(@image, false)) data-width=@image.image_width data-height=@image.image_height = if @image.image_mime_type == "video/webm" do diff --git a/lib/philomena_web/templates/profile/show.html.slime b/lib/philomena_web/templates/profile/show.html.slime index 56cf5d05..8077732d 100644 --- a/lib/philomena_web/templates/profile/show.html.slime +++ b/lib/philomena_web/templates/profile/show.html.slime @@ -49,7 +49,7 @@ .block__content.alternating-color.break-word .center = if link.tag do - .tag_list = render PhilomenaWeb.TagView, "_tag.html", tag: link.tag + .tag_list = render PhilomenaWeb.TagView, "_tag.html", tag: link.tag, conn: @conn = link(link.uri, to: link.uri) .block diff --git a/lib/philomena_web/templates/search/reverse/index.html.slime b/lib/philomena_web/templates/search/reverse/index.html.slime index 343d1b75..17efef77 100644 --- a/lib/philomena_web/templates/search/reverse/index.html.slime +++ b/lib/philomena_web/templates/search/reverse/index.html.slime @@ -66,7 +66,7 @@ h1 Reverse Search => round(match.image_size / 1024) ' KiB - = render PhilomenaWeb.TagView, "_tag_list.html", tags: Tag.display_order(match.tags) + = render PhilomenaWeb.TagView, "_tag_list.html", tags: Tag.display_order(match.tags), conn: @conn - true -> h2 Results diff --git a/lib/philomena_web/templates/tag/_tag.html.slime b/lib/philomena_web/templates/tag/_tag.html.slime index 217783c5..90efbbf5 100644 --- a/lib/philomena_web/templates/tag/_tag.html.slime +++ b/lib/philomena_web/templates/tag/_tag.html.slime @@ -15,14 +15,14 @@ span.tag.dropdown data-tag-category="#{@tag.category}" data-tag-id="#{@tag.id}" span.tag__state.hidden title="Hidden" | H span.dropdown__content - a.tag__dropdown__link.hidden data-method="delete" data-remote="true" data-tag-action="unwatch" href="/tags/#{@tag.slug}/watch" Unwatch - a.tag__dropdown__link.hidden data-method="post" data-remote="true" data-tag-action="watch" href="/tags/#{@tag.slug}/watch" Watch + a.tag__dropdown__link.hidden data-method="delete" data-remote="true" data-tag-action="unwatch" href=Routes.tag_watch_path(@conn, :delete, @tag) Unwatch + a.tag__dropdown__link.hidden data-method="post" data-remote="true" data-tag-action="watch" href=Routes.tag_watch_path(@conn, :create, @tag) Watch - a.tag__dropdown__link.hidden data-method="delete" data-remote="true" data-tag-action="unspoiler" href="/filters/spoiler?tagname=#{@tag.slug}" Unspoiler - a.tag__dropdown__link.hidden data-method="post" data-remote="true" data-tag-action="spoiler" href="/filters/spoiler?tagname=#{@tag.slug}" Spoiler + a.tag__dropdown__link.hidden data-method="delete" data-remote="true" data-tag-action="unspoiler" href=Routes.filter_spoiler_path(@conn, :delete, tag: @tag) Unspoiler + a.tag__dropdown__link.hidden data-method="post" data-remote="true" data-tag-action="spoiler" href=Routes.filter_spoiler_path(@conn, :create, tag: @tag) Spoiler - a.tag__dropdown__link.hidden data-method="delete" data-remote="true" data-tag-action="unhide" href="/filters/hide?tagname=#{@tag.slug}" Unhide - a.tag__dropdown__link.hidden data-method="post" data-remote="true" data-tag-action="hide" href="/filters/hide?tagname=#{@tag.slug}" Hide + a.tag__dropdown__link.hidden data-method="delete" data-remote="true" data-tag-action="unhide" href=Routes.filter_hide_path(@conn, :delete, tag: @tag) Unhide + a.tag__dropdown__link.hidden data-method="post" data-remote="true" data-tag-action="hide" href=Routes.filter_hide_path(@conn, :create, tag: @tag) Hide a.tag__dropdown__link.hidden href="/users/sign_in" Sign in to Watch a.tag__dropdown__link.hidden href="/filters" Filter \ No newline at end of file diff --git a/lib/philomena_web/templates/tag/_tag_info_row.html.slime b/lib/philomena_web/templates/tag/_tag_info_row.html.slime index 100c7675..033e3973 100644 --- a/lib/philomena_web/templates/tag/_tag_info_row.html.slime +++ b/lib/philomena_web/templates/tag/_tag_info_row.html.slime @@ -6,7 +6,7 @@ | no spoiler image .flex__grow - = render PhilomenaWeb.TagView, "_tag.html", tag: @tag + = render PhilomenaWeb.TagView, "_tag.html", tag: @tag, conn: @conn = link "Tag changes", to: Routes.tag_tag_change_path(@conn, :index, @tag), class: "detail-link" br diff --git a/lib/philomena_web/templates/tag/_tag_list.html.slime b/lib/philomena_web/templates/tag/_tag_list.html.slime index 42d4ddb4..ea9562cc 100644 --- a/lib/philomena_web/templates/tag/_tag_list.html.slime +++ b/lib/philomena_web/templates/tag/_tag_list.html.slime @@ -1,3 +1,3 @@ .tag-list = for tag <- @tags do - = render PhilomenaWeb.TagView, "_tag.html", tag: tag \ No newline at end of file + = render PhilomenaWeb.TagView, "_tag.html", tag: tag, conn: @conn \ No newline at end of file diff --git a/lib/philomena_web/templates/tag/index.html.slime b/lib/philomena_web/templates/tag/index.html.slime index edf1f541..15d33a61 100644 --- a/lib/philomena_web/templates/tag/index.html.slime +++ b/lib/philomena_web/templates/tag/index.html.slime @@ -18,7 +18,7 @@ h2 Search Results - route = fn p -> Routes.tag_path(@conn, :index, p) end - pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @tags, route: route - = render PhilomenaWeb.TagView, "_tag_list.html", tags: @tags + = render PhilomenaWeb.TagView, "_tag_list.html", tags: @tags, conn: @conn .block .block__header.block__header--light.flex diff --git a/lib/philomena_web/templates/user_link/show.html.slime b/lib/philomena_web/templates/user_link/show.html.slime index a15761b9..f7b32605 100644 --- a/lib/philomena_web/templates/user_link/show.html.slime +++ b/lib/philomena_web/templates/user_link/show.html.slime @@ -52,7 +52,7 @@ h3 Visibility h3 Associated tag = if @user_link.tag do p - = render PhilomenaWeb.TagView, "_tag.html", tag: @user_link.tag + = render PhilomenaWeb.TagView, "_tag.html", tag: @user_link.tag, conn: @conn - else p There is no tag associated with this link.