mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-23 20:18:00 +01:00
User settings (#96)
Resolves derpibooru/philomena#121 Resolves derpibooru/philomena#122
This commit is contained in:
parent
8f3965b9f5
commit
767a2ba949
15 changed files with 226 additions and 67 deletions
|
@ -18,6 +18,7 @@ defmodule Philomena.Comments do
|
|||
alias Philomena.NotificationWorker
|
||||
alias Philomena.Versions
|
||||
alias Philomena.Reports
|
||||
alias Philomena.Users.User
|
||||
|
||||
@doc """
|
||||
Gets a single comment.
|
||||
|
@ -59,12 +60,21 @@ defmodule Philomena.Comments do
|
|||
Multi.new()
|
||||
|> Multi.insert(:comment, comment)
|
||||
|> Multi.update_all(:image, image_query, inc: [comments_count: 1])
|
||||
|> Multi.run(:subscribe, fn _repo, _changes ->
|
||||
Images.create_subscription(image, attribution[:user])
|
||||
end)
|
||||
|> maybe_create_subscription_on_reply(image, attribution[:user])
|
||||
|> Repo.transaction()
|
||||
end
|
||||
|
||||
defp maybe_create_subscription_on_reply(multi, image, %User{watch_on_reply: true} = user) do
|
||||
multi
|
||||
|> Multi.run(:subscribe, fn _repo, _changes ->
|
||||
Images.create_subscription(image, user)
|
||||
end)
|
||||
end
|
||||
|
||||
defp maybe_create_subscription_on_reply(multi, _image, _user) do
|
||||
multi
|
||||
end
|
||||
|
||||
def notify_comment(comment) do
|
||||
Exq.enqueue(Exq, "notifications", NotificationWorker, ["Comments", comment.id])
|
||||
end
|
||||
|
|
|
@ -34,6 +34,7 @@ defmodule Philomena.Images do
|
|||
alias Philomena.Comments
|
||||
alias Philomena.Galleries.Gallery
|
||||
alias Philomena.Galleries.Interaction
|
||||
alias Philomena.Users.User
|
||||
|
||||
@doc """
|
||||
Gets a single image.
|
||||
|
@ -95,9 +96,7 @@ defmodule Philomena.Images do
|
|||
|
||||
{:ok, count}
|
||||
end)
|
||||
|> Multi.run(:subscribe, fn _repo, %{image: image} ->
|
||||
create_subscription(image, attribution[:user])
|
||||
end)
|
||||
|> maybe_create_subscription_on_upload(attribution[:user])
|
||||
|> Repo.transaction()
|
||||
|> case do
|
||||
{:ok, %{image: image}} = result ->
|
||||
|
@ -116,6 +115,17 @@ defmodule Philomena.Images do
|
|||
end
|
||||
end
|
||||
|
||||
defp maybe_create_subscription_on_upload(multi, %User{watch_on_upload: true} = user) do
|
||||
multi
|
||||
|> Multi.run(:subscribe, fn _repo, %{image: image} ->
|
||||
create_subscription(image, user)
|
||||
end)
|
||||
end
|
||||
|
||||
defp maybe_create_subscription_on_upload(multi, _user) do
|
||||
multi
|
||||
end
|
||||
|
||||
def feature_image(featurer, %Image{} = image) do
|
||||
%ImageFeature{user_id: featurer.id, image_id: image.id}
|
||||
|> ImageFeature.changeset(%{})
|
||||
|
|
|
@ -19,6 +19,7 @@ defmodule Philomena.Posts do
|
|||
alias Philomena.Versions
|
||||
alias Philomena.Reports
|
||||
alias Philomena.Reports.Report
|
||||
alias Philomena.Users.User
|
||||
|
||||
@doc """
|
||||
Gets a single post.
|
||||
|
@ -88,9 +89,7 @@ defmodule Philomena.Posts do
|
|||
|
||||
{:ok, count}
|
||||
end)
|
||||
|> Multi.run(:subscribe, fn _repo, _changes ->
|
||||
Topics.create_subscription(topic, attributes[:user])
|
||||
end)
|
||||
|> maybe_create_subscription_on_reply(topic, attributes[:user])
|
||||
|> Repo.transaction()
|
||||
|> case do
|
||||
{:ok, %{post: post}} = result ->
|
||||
|
@ -103,6 +102,17 @@ defmodule Philomena.Posts do
|
|||
end
|
||||
end
|
||||
|
||||
defp maybe_create_subscription_on_reply(multi, topic, %User{watch_on_reply: true} = user) do
|
||||
multi
|
||||
|> Multi.run(:subscribe, fn _repo, _changes ->
|
||||
Topics.create_subscription(topic, user)
|
||||
end)
|
||||
end
|
||||
|
||||
defp maybe_create_subscription_on_reply(multi, _topic, _user) do
|
||||
multi
|
||||
end
|
||||
|
||||
def notify_post(post) do
|
||||
Exq.enqueue(Exq, "notifications", NotificationWorker, ["Posts", post.id])
|
||||
end
|
||||
|
|
|
@ -12,6 +12,7 @@ defmodule Philomena.Topics do
|
|||
alias Philomena.Posts
|
||||
alias Philomena.Notifications
|
||||
alias Philomena.NotificationWorker
|
||||
alias Philomena.Users.User
|
||||
|
||||
@doc """
|
||||
Gets a single topic.
|
||||
|
@ -69,9 +70,7 @@ defmodule Philomena.Topics do
|
|||
|
||||
{:ok, count}
|
||||
end)
|
||||
|> Multi.run(:subscribe, fn _repo, %{topic: topic} ->
|
||||
create_subscription(topic, attribution[:user])
|
||||
end)
|
||||
|> maybe_create_subscription_on_new_topic(attribution[:user])
|
||||
|> Repo.transaction()
|
||||
|> case do
|
||||
{:ok, %{topic: topic}} = result ->
|
||||
|
@ -84,6 +83,17 @@ defmodule Philomena.Topics do
|
|||
end
|
||||
end
|
||||
|
||||
defp maybe_create_subscription_on_new_topic(multi, %User{watch_on_new_topic: true} = user) do
|
||||
multi
|
||||
|> Multi.run(:subscribe, fn _repo, %{topic: topic} ->
|
||||
create_subscription(topic, user)
|
||||
end)
|
||||
end
|
||||
|
||||
defp maybe_create_subscription_on_new_topic(multi, _user) do
|
||||
multi
|
||||
end
|
||||
|
||||
def notify_topic(topic, post) do
|
||||
Exq.enqueue(Exq, "notifications", NotificationWorker, ["Topics", [topic.id, post.id]])
|
||||
end
|
||||
|
|
|
@ -654,6 +654,12 @@ defmodule Philomena.Users do
|
|||
|> Repo.update()
|
||||
end
|
||||
|
||||
def clear_recent_filters(%User{} = user) do
|
||||
user
|
||||
|> User.clear_recent_filters_changeset()
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
defp load_with_roles(query) do
|
||||
query
|
||||
|> Repo.one()
|
||||
|
|
|
@ -314,7 +314,13 @@ defmodule Philomena.Users.User do
|
|||
:watched_images_exclude_str,
|
||||
:use_centered_layout,
|
||||
:hide_vote_counts,
|
||||
:comments_newest_first
|
||||
:comments_newest_first,
|
||||
:watch_on_reply,
|
||||
:watch_on_upload,
|
||||
:watch_on_new_topic,
|
||||
:comments_always_jump_to_last,
|
||||
:messages_newest_first,
|
||||
:show_sidebar_and_watched_images
|
||||
])
|
||||
|> validate_required([
|
||||
:images_per_page,
|
||||
|
@ -326,7 +332,13 @@ defmodule Philomena.Users.User do
|
|||
:theme,
|
||||
:no_spoilered_in_watched,
|
||||
:use_centered_layout,
|
||||
:hide_vote_counts
|
||||
:hide_vote_counts,
|
||||
:watch_on_reply,
|
||||
:watch_on_upload,
|
||||
:watch_on_new_topic,
|
||||
:comments_always_jump_to_last,
|
||||
:messages_newest_first,
|
||||
:show_sidebar_and_watched_images
|
||||
])
|
||||
|> TagList.propagate_tag_list(:watched_tag_list, :watched_tag_ids)
|
||||
|> validate_inclusion(:theme, ~W(default dark red))
|
||||
|
@ -511,6 +523,13 @@ defmodule Philomena.Users.User do
|
|||
)
|
||||
end
|
||||
|
||||
def clear_recent_filters_changeset(user) do
|
||||
user
|
||||
|> change(%{
|
||||
recent_filter_ids: [user.current_filter_id]
|
||||
})
|
||||
end
|
||||
|
||||
defp enable_totp_changeset(user, backup_codes) do
|
||||
hashed_codes = Enum.map(backup_codes, &Password.hash_pwd_salt/1)
|
||||
|
||||
|
|
|
@ -34,6 +34,18 @@ defmodule PhilomenaWeb.CommentLoader do
|
|||
div(offset, page_size) + 1
|
||||
end
|
||||
|
||||
def last_page(conn, image) do
|
||||
offset =
|
||||
Comment
|
||||
|> where(image_id: ^image.id)
|
||||
|> Repo.aggregate(:count, :id)
|
||||
|
||||
page_size = conn.assigns.comment_scrivener[:page_size]
|
||||
|
||||
# Pagination starts at page 1
|
||||
div(offset, page_size) + 1
|
||||
end
|
||||
|
||||
defp load_direction(%{comments_newest_first: false}), do: :asc
|
||||
defp load_direction(_user), do: :desc
|
||||
|
||||
|
|
|
@ -116,7 +116,8 @@ defmodule PhilomenaWeb.ActivityController do
|
|||
streams: streams,
|
||||
topics: topics,
|
||||
interactions: interactions,
|
||||
layout_class: "layout--wide"
|
||||
layout_class: "layout--wide",
|
||||
show_sidebar: show_sidebar?(user) || !index_page?(conn)
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -165,4 +166,12 @@ defmodule PhilomenaWeb.ActivityController do
|
|||
]
|
||||
)
|
||||
end
|
||||
|
||||
defp index_page?(%{assigns: %{index: true}}), do: true
|
||||
|
||||
defp index_page?(_conn), do: false
|
||||
|
||||
defp show_sidebar?(%{show_sidebar_and_watched_images: false}), do: false
|
||||
|
||||
defp show_sidebar?(_user), do: true
|
||||
end
|
||||
|
|
|
@ -61,11 +61,12 @@ defmodule PhilomenaWeb.ConversationController do
|
|||
def show(conn, _params) do
|
||||
conversation = conn.assigns.conversation
|
||||
user = conn.assigns.current_user
|
||||
pref = load_direction(user)
|
||||
|
||||
messages =
|
||||
Message
|
||||
|> where(conversation_id: ^conversation.id)
|
||||
|> order_by(asc: :created_at)
|
||||
|> order_by([{^pref, :created_at}])
|
||||
|> preload([:from])
|
||||
|> Repo.paginate(conn.assigns.scrivener)
|
||||
|
||||
|
@ -115,4 +116,7 @@ defmodule PhilomenaWeb.ConversationController do
|
|||
|> render("new.html", changeset: changeset)
|
||||
end
|
||||
end
|
||||
|
||||
defp load_direction(%{messages_newest_first: false}), do: :asc
|
||||
defp load_direction(_user), do: :desc
|
||||
end
|
||||
|
|
15
lib/philomena_web/controllers/filter/clear_recent.ex
Normal file
15
lib/philomena_web/controllers/filter/clear_recent.ex
Normal file
|
@ -0,0 +1,15 @@
|
|||
defmodule PhilomenaWeb.Filter.ClearRecentController do
|
||||
use PhilomenaWeb, :controller
|
||||
|
||||
alias Philomena.Users
|
||||
|
||||
plug PhilomenaWeb.RequireUserPlug
|
||||
|
||||
def delete(conn, _params) do
|
||||
{:ok, user} = Users.clear_recent_filters(conn.assigns.current_user)
|
||||
|
||||
conn
|
||||
|> put_flash(:info, "Cleared recent filters")
|
||||
|> redirect(external: conn.assigns.referrer)
|
||||
end
|
||||
end
|
|
@ -59,6 +59,8 @@ defmodule PhilomenaWeb.ImageController do
|
|||
# Update the notification ticker in the header
|
||||
conn = NotificationCountPlug.call(conn)
|
||||
|
||||
conn = maybe_skip_to_last_comment_page(conn, image, user)
|
||||
|
||||
comments = CommentLoader.load_comments(conn, image)
|
||||
|
||||
rendered = TextileRenderer.render_collection(comments.entries, conn)
|
||||
|
@ -132,6 +134,14 @@ defmodule PhilomenaWeb.ImageController do
|
|||
end
|
||||
end
|
||||
|
||||
defp maybe_skip_to_last_comment_page(conn, image, %{comments_newest_first: false, comments_always_jump_to_last: true}) do
|
||||
page = CommentLoader.last_page(conn, image)
|
||||
conn
|
||||
|> assign(:comment_scrivener, Keyword.merge(conn.assigns.comment_scrivener, [page: page]))
|
||||
end
|
||||
|
||||
defp maybe_skip_to_last_comment_page(conn, _image, _user), do: conn
|
||||
|
||||
defp user_galleries(_image, nil), do: []
|
||||
|
||||
defp user_galleries(image, user) do
|
||||
|
|
|
@ -418,7 +418,7 @@ defmodule PhilomenaWeb.Router do
|
|||
scope "/", PhilomenaWeb do
|
||||
pipe_through [:browser, :ensure_totp, :ensure_tor_authorized]
|
||||
|
||||
get "/", ActivityController, :index
|
||||
get "/", ActivityController, :index, [assigns: %{index: true}]
|
||||
|
||||
resources "/activity", ActivityController, only: [:index]
|
||||
|
||||
|
@ -474,6 +474,7 @@ defmodule PhilomenaWeb.Router do
|
|||
|
||||
scope "/filters", Filter, as: :filter do
|
||||
resources "/current", CurrentController, only: [:update], singleton: true
|
||||
resources "/clear_recent", ClearRecentController, only: [:delete], singleton: true
|
||||
end
|
||||
|
||||
resources "/filters", FilterController do
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
.column-layout
|
||||
= if @show_sidebar do
|
||||
aside.column-layout__left#activity-side
|
||||
= if not is_nil(@featured_image) and not PhilomenaWeb.ImageView.filter_or_spoiler_hits?(@conn, @featured_image) do
|
||||
.center
|
||||
|
@ -39,7 +40,7 @@
|
|||
|
||||
.column-layout__main
|
||||
= render PhilomenaWeb.ImageView, "index.html", conn: @conn, images: @images, size: :thumb
|
||||
= if not is_nil(@watched) and Enum.any?(@watched) do
|
||||
= if @show_sidebar and not is_nil(@watched) and Enum.any?(@watched) do
|
||||
.block
|
||||
.block__header
|
||||
span.block__header__title
|
||||
|
|
|
@ -39,6 +39,12 @@
|
|||
= for filter <- @system_filters do
|
||||
= render PhilomenaWeb.FilterView, "_filter.html", conn: @conn, filter: filter
|
||||
|
||||
= if @current_user do
|
||||
h2 Recent Filters
|
||||
p
|
||||
' Clicking this button will clear the recent filters list in the header dropdown.
|
||||
= button_to "Clear recent filter list", Routes.filter_clear_recent_path(@conn, :delete), method: "delete", class: "button"
|
||||
|
||||
h2 Search Filters
|
||||
p
|
||||
' Some users maintain custom filters which are publicly shared; you can search these filters with the box below.
|
||||
|
@ -50,7 +56,7 @@
|
|||
.fieldlabel
|
||||
' For more information, see the
|
||||
a href="/pages/search_syntax" search syntax documentation
|
||||
' . Search results are sorted by creation date.
|
||||
' . Search results are sorted alphabetically.
|
||||
|
||||
= if @conn.params["fq"] do
|
||||
h2 Search Results
|
||||
|
@ -107,7 +113,7 @@ table.table
|
|||
td Full Text
|
||||
td Matches the description of this filter.
|
||||
td
|
||||
code = link "description:show's rating", to: Routes.filter_path(@conn, :index, fq: "description:the show's rating")
|
||||
code = link "description:the show's rating", to: Routes.filter_path(@conn, :index, fq: "description:the show's rating")
|
||||
tr
|
||||
td
|
||||
code created_at
|
||||
|
|
|
@ -9,6 +9,8 @@ h1 Content Settings
|
|||
= if @conn.assigns.current_user do
|
||||
= link "Watch List", to: "#", class: "selected", data: [click_tab: "watched"]
|
||||
= link "Display", to: "#", data: [click_tab: "display"]
|
||||
= link "Comments", to: "#", data: [click_tab: "comments"]
|
||||
= link "Notifications", to: "#", data: [click_tab: "notifications"]
|
||||
= link "Metadata", to: "#", data: [click_tab: "metadata"]
|
||||
= link "Local", to: "#", data: [click_tab: "local"]
|
||||
- else
|
||||
|
@ -55,14 +57,14 @@ h1 Content Settings
|
|||
=> label f, :use_centered_layout
|
||||
=> checkbox f, :use_centered_layout, class: "checkbox"
|
||||
.fieldlabel: i Align content to the center of the page - try this option out if you browse the site on a tablet or a fairly wide screen.
|
||||
.field
|
||||
=> label f, :show_sidebar_and_watched_images
|
||||
=> checkbox f, :show_sidebar_and_watched_images, class: "checkbox"
|
||||
.fieldlabel: i Show the sidebar and new watched images on the homepage (the default) or hide it.
|
||||
.field
|
||||
=> label f, :hide_vote_counts
|
||||
=> checkbox f, :hide_vote_counts, class: "checkbox"
|
||||
.fieldlabel: i Hide upvote and downvote counts on images, showing only the overall score
|
||||
.field
|
||||
=> label f, :comments_newest_first, "Newest comments first"
|
||||
=> checkbox f, :comments_newest_first
|
||||
.fieldlabel: i Display the newest comments at the top of the page.
|
||||
.field
|
||||
=> label f, :images_per_page
|
||||
=> number_input f, :images_per_page, min: 1, max: 50, step: 1, class: "input"
|
||||
|
@ -71,11 +73,6 @@ h1 Content Settings
|
|||
i
|
||||
' This is the number of images per page that are displayed on image listings and searches, up to a maximum of 50.
|
||||
' For 1080p monitors, try 24.
|
||||
.field
|
||||
=> label f, :comments_per_page
|
||||
=> number_input f, :comments_per_page, min: 1, max: 100, step: 1, class: "input"
|
||||
= error_tag f, :comments_per_page
|
||||
.fieldlabel: i This is the number of comments per page that are displayed on image pages.
|
||||
.field
|
||||
=> label f, :scale_large_images
|
||||
=> checkbox f, :scale_large_images, class: "checkbox"
|
||||
|
@ -86,6 +83,45 @@ h1 Content Settings
|
|||
= error_tag f, :theme
|
||||
.fieldlabel: i Preview themes by selecting one from the dropdown. Saving sets the currently selected theme.
|
||||
|
||||
.block__tab.hidden.flex.flex--maybe-wrap data-tab="comments"
|
||||
div
|
||||
.field
|
||||
=> label f, :comments_newest_first, "Newest comments first"
|
||||
=> checkbox f, :comments_newest_first
|
||||
.fieldlabel: i Display the newest comments at the top of the page.
|
||||
.field
|
||||
=> label f, :comments_always_jump_to_last, "Show latest comment page"
|
||||
=> checkbox f, :comments_always_jump_to_last
|
||||
.fieldlabel
|
||||
i
|
||||
' This setting takes effect when the previous is disabled. Always jump to the latest page (enabled) or show the first page if the oldest comments are shown at the top of the page.
|
||||
br
|
||||
' Posting will always direct you to the latest page so that you can see your comment in context.
|
||||
.field
|
||||
=> label f, :comments_per_page
|
||||
=> number_input f, :comments_per_page, min: 1, max: 100, step: 1, class: "input"
|
||||
= error_tag f, :comments_per_page
|
||||
.fieldlabel: i This is the number of comments per page that are displayed on image pages.
|
||||
.field
|
||||
=> label f, :messages_newest_first, "Newest messages first"
|
||||
=> checkbox f, :messages_newest_first
|
||||
.fieldlabel: i Show the newest messages first (enabled) or show the oldest messages at the top of a conversation. Enabling this makes it feel more like a top-posted email quote chain.
|
||||
|
||||
.block__tab.hidden.flex.flex--maybe-wrap data-tab="notifications"
|
||||
div
|
||||
.field
|
||||
=> label f, :watch_on_reply, "Subscribe on Reply"
|
||||
=> checkbox f, :watch_on_reply, class: "checkbox"
|
||||
.fieldlabel: i Subscribe on Reply means you'll be subscribed things (images or topics) automatically as soon as you post a comment or reply, keeping you in the conversation.
|
||||
.field
|
||||
=> label f, :watch_on_upload, "Subscribe on Upload"
|
||||
=> checkbox f, :watch_on_upload, class: "checkbox"
|
||||
.fieldlabel: i Subscribe on Upload means you'll be subscribed to images automatically as soon as you upload, to help you keep track of comments.
|
||||
.field
|
||||
=> label f, :watch_on_new_topic, "Subscribe on New Threads"
|
||||
=> checkbox f, :watch_on_new_topic, class: "checkbox"
|
||||
.fieldlabel: i Subscribe on New Threads means you'll be subscribed to threads automatically as soon as you post, to help you keep track of replies.
|
||||
|
||||
.block__tab.hidden.flex.flex--maybe-wrap data-tab="metadata"
|
||||
div
|
||||
.field
|
||||
|
|
Loading…
Reference in a new issue