Merge branch 'bugfix/emoji-size' into 'develop'
Bugfix: emoji size in profile Closes #269 See merge request pleroma/pleroma!792
This commit is contained in:
commit
4948a73e37
@ -113,9 +113,7 @@ def emojify(text, emoji, strip \\ false) do
|
||||
|
||||
html =
|
||||
if not strip do
|
||||
"<img height='32px' width='32px' alt='#{emoji}' title='#{emoji}' src='#{
|
||||
MediaProxy.url(file)
|
||||
}' />"
|
||||
"<img class='emoji' alt='#{emoji}' title='#{emoji}' src='#{MediaProxy.url(file)}' />"
|
||||
else
|
||||
""
|
||||
end
|
||||
@ -130,12 +128,23 @@ def demojify(text) do
|
||||
|
||||
def demojify(text, nil), do: text
|
||||
|
||||
@doc "Outputs a list of the emoji-shortcodes in a text"
|
||||
def get_emoji(text) when is_binary(text) do
|
||||
Enum.filter(Emoji.get_all(), fn {emoji, _, _} -> String.contains?(text, ":#{emoji}:") end)
|
||||
end
|
||||
|
||||
def get_emoji(_), do: []
|
||||
|
||||
@doc "Outputs a list of the emoji-Maps in a text"
|
||||
def get_emoji_map(text) when is_binary(text) do
|
||||
get_emoji(text)
|
||||
|> Enum.reduce(%{}, fn {name, file, _group}, acc ->
|
||||
Map.put(acc, name, "#{Pleroma.Web.Endpoint.static_url()}#{file}")
|
||||
end)
|
||||
end
|
||||
|
||||
def get_emoji_map(_), do: []
|
||||
|
||||
def html_escape({text, mentions, hashtags}, type) do
|
||||
{html_escape(text, type), mentions, hashtags}
|
||||
end
|
||||
|
@ -151,6 +151,7 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
|
||||
Meta.allow_tag_with_these_attributes("img", [
|
||||
"width",
|
||||
"height",
|
||||
"class",
|
||||
"title",
|
||||
"alt"
|
||||
])
|
||||
@ -221,6 +222,7 @@ defmodule Pleroma.HTML.Scrubber.Default do
|
||||
Meta.allow_tag_with_these_attributes("img", [
|
||||
"width",
|
||||
"height",
|
||||
"class",
|
||||
"title",
|
||||
"alt"
|
||||
])
|
||||
|
@ -11,7 +11,6 @@ defmodule Pleroma.User do
|
||||
alias Comeonin.Pbkdf2
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Registration
|
||||
@ -1331,18 +1330,15 @@ def wait_and_refresh(timeout, %User{} = a, %User{} = b) do
|
||||
end
|
||||
end
|
||||
|
||||
def parse_bio(bio, user \\ %User{info: %{source_data: %{}}})
|
||||
def parse_bio(nil, _user), do: ""
|
||||
def parse_bio(bio, _user) when bio == "", do: bio
|
||||
def parse_bio(bio) when is_binary(bio) and bio != "" do
|
||||
bio
|
||||
|> CommonUtils.format_input("text/plain", mentions_format: :full)
|
||||
|> elem(0)
|
||||
end
|
||||
|
||||
def parse_bio(bio, user) do
|
||||
emoji =
|
||||
(user.info.source_data["tag"] || [])
|
||||
|> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
|
||||
|> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
|
||||
{String.trim(name, ":"), url}
|
||||
end)
|
||||
def parse_bio(_), do: ""
|
||||
|
||||
def parse_bio(bio, user) when is_binary(bio) and bio != "" do
|
||||
# TODO: get profile URLs other than user.ap_id
|
||||
profile_urls = [user.ap_id]
|
||||
|
||||
@ -1352,9 +1348,10 @@ def parse_bio(bio, user) do
|
||||
rel: &RelMe.maybe_put_rel_me(&1, profile_urls)
|
||||
)
|
||||
|> elem(0)
|
||||
|> Formatter.emojify(emoji)
|
||||
end
|
||||
|
||||
def parse_bio(_, _), do: ""
|
||||
|
||||
def tag(user_identifiers, tags) when is_list(user_identifiers) do
|
||||
Repo.transaction(fn ->
|
||||
for user_identifier <- user_identifiers, do: tag(user_identifier, tags)
|
||||
|
@ -41,6 +41,7 @@ defmodule Pleroma.User.Info do
|
||||
field(:hide_favorites, :boolean, default: true)
|
||||
field(:pinned_activities, {:array, :string}, default: [])
|
||||
field(:flavour, :string, default: nil)
|
||||
field(:emoji, {:array, :map}, default: [])
|
||||
|
||||
field(:notification_settings, :map,
|
||||
default: %{"remote" => true, "local" => true, "followers" => true, "follows" => true}
|
||||
|
@ -856,10 +856,16 @@ def add_mention_tags(object) do
|
||||
|> Map.put("tag", tags ++ mentions)
|
||||
end
|
||||
|
||||
def add_emoji_tags(%User{info: %{"emoji" => _emoji} = user_info} = object) do
|
||||
user_info = add_emoji_tags(user_info)
|
||||
|
||||
object
|
||||
|> Map.put(:info, user_info)
|
||||
end
|
||||
|
||||
# TODO: we should probably send mtime instead of unix epoch time for updated
|
||||
def add_emoji_tags(object) do
|
||||
def add_emoji_tags(%{"emoji" => emoji} = object) do
|
||||
tags = object["tag"] || []
|
||||
emoji = object["emoji"] || []
|
||||
|
||||
out =
|
||||
emoji
|
||||
@ -877,6 +883,10 @@ def add_emoji_tags(object) do
|
||||
|> Map.put("tag", tags ++ out)
|
||||
end
|
||||
|
||||
def add_emoji_tags(object) do
|
||||
object
|
||||
end
|
||||
|
||||
def set_conversation(object) do
|
||||
Map.put(object, "conversation", object["context"])
|
||||
end
|
||||
|
@ -69,6 +69,11 @@ def render("user.json", %{user: user}) do
|
||||
|
||||
endpoints = render("endpoints.json", %{user: user})
|
||||
|
||||
user_tags =
|
||||
user
|
||||
|> Transmogrifier.add_emoji_tags()
|
||||
|> Map.get("tag", [])
|
||||
|
||||
%{
|
||||
"id" => user.ap_id,
|
||||
"type" => "Person",
|
||||
@ -87,7 +92,7 @@ def render("user.json", %{user: user}) do
|
||||
"publicKeyPem" => public_key
|
||||
},
|
||||
"endpoints" => endpoints,
|
||||
"tag" => user.info.source_data["tag"] || []
|
||||
"tag" => (user.info.source_data["tag"] || []) ++ user_tags
|
||||
}
|
||||
|> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user))
|
||||
|> Map.merge(maybe_make_image(&User.banner_url/2, "image", user))
|
||||
|
@ -151,8 +151,8 @@ def post(user, %{"status" => status} = data) do
|
||||
),
|
||||
{to, cc} <- to_for_user_and_mentions(user, mentions, in_reply_to, visibility),
|
||||
context <- make_context(in_reply_to),
|
||||
cw <- data["spoiler_text"],
|
||||
full_payload <- String.trim(status <> (data["spoiler_text"] || "")),
|
||||
cw <- data["spoiler_text"] || "",
|
||||
full_payload <- String.trim(status <> cw),
|
||||
length when length in 1..limit <- String.length(full_payload),
|
||||
object <-
|
||||
make_note_data(
|
||||
@ -170,10 +170,7 @@ def post(user, %{"status" => status} = data) do
|
||||
Map.put(
|
||||
object,
|
||||
"emoji",
|
||||
(Formatter.get_emoji(status) ++ Formatter.get_emoji(data["spoiler_text"]))
|
||||
|> Enum.reduce(%{}, fn {name, file, _}, acc ->
|
||||
Map.put(acc, name, "#{Pleroma.Web.Endpoint.static_url()}#{file}")
|
||||
end)
|
||||
Formatter.get_emoji_map(full_payload)
|
||||
) do
|
||||
res =
|
||||
ActivityPub.create(
|
||||
|
@ -9,6 +9,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Filter
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Object.Fetcher
|
||||
@ -86,7 +87,7 @@ def update_credentials(%{assigns: %{user: user}} = conn, params) do
|
||||
user_params =
|
||||
%{}
|
||||
|> add_if_present(params, "display_name", :name)
|
||||
|> add_if_present(params, "note", :bio, fn value -> {:ok, User.parse_bio(value)} end)
|
||||
|> add_if_present(params, "note", :bio, fn value -> {:ok, User.parse_bio(value, user)} end)
|
||||
|> add_if_present(params, "avatar", :avatar, fn value ->
|
||||
with %Plug.Upload{} <- value,
|
||||
{:ok, object} <- ActivityPub.upload(value, type: :avatar) do
|
||||
@ -96,6 +97,12 @@ def update_credentials(%{assigns: %{user: user}} = conn, params) do
|
||||
end
|
||||
end)
|
||||
|
||||
emojis_text = (user_params["display_name"] || "") <> (user_params["note"] || "")
|
||||
|
||||
user_info_emojis =
|
||||
((user.info.emoji || []) ++ Formatter.get_emoji_map(emojis_text))
|
||||
|> Enum.dedup()
|
||||
|
||||
info_params =
|
||||
[:no_rich_text, :locked, :hide_followers, :hide_follows, :hide_favorites, :show_role]
|
||||
|> Enum.reduce(%{}, fn key, acc ->
|
||||
@ -112,6 +119,7 @@ def update_credentials(%{assigns: %{user: user}} = conn, params) do
|
||||
_ -> :error
|
||||
end
|
||||
end)
|
||||
|> Map.put(:emoji, user_info_emojis)
|
||||
|
||||
info_cng = User.Info.profile_update(user.info, info_params)
|
||||
|
||||
|
@ -9,6 +9,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|
||||
|
||||
alias Ecto.Changeset
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
@ -653,7 +654,22 @@ defp build_info_cng(user, params) do
|
||||
|
||||
defp parse_profile_bio(user, params) do
|
||||
if bio = params["description"] do
|
||||
Map.put(params, "bio", User.parse_bio(bio, user))
|
||||
emojis_text = (params["description"] || "") <> " " <> (params["name"] || "")
|
||||
|
||||
emojis =
|
||||
((user.info.emoji || []) ++ Formatter.get_emoji_map(emojis_text))
|
||||
|> Enum.dedup()
|
||||
|
||||
user_info =
|
||||
user.info
|
||||
|> Map.put(
|
||||
"emoji",
|
||||
emojis
|
||||
)
|
||||
|
||||
params
|
||||
|> Map.put("bio", User.parse_bio(bio, user))
|
||||
|> Map.put("info", user_info)
|
||||
else
|
||||
params
|
||||
end
|
||||
|
@ -67,6 +67,13 @@ defp do_render("user.json", %{user: user = %User{}} = assigns) do
|
||||
{String.trim(name, ":"), url}
|
||||
end)
|
||||
|
||||
emoji = Enum.dedup(emoji ++ user.info.emoji)
|
||||
|
||||
description_html =
|
||||
(user.bio || "")
|
||||
|> HTML.filter_tags(User.html_filter_policy(for_user))
|
||||
|> Formatter.emojify(emoji)
|
||||
|
||||
# ``fields`` is an array of mastodon profile field, containing ``{"name": "…", "value": "…"}``.
|
||||
# For example: [{"name": "Pronoun", "value": "she/her"}, …]
|
||||
fields =
|
||||
@ -78,7 +85,7 @@ defp do_render("user.json", %{user: user = %User{}} = assigns) do
|
||||
%{
|
||||
"created_at" => user.inserted_at |> Utils.format_naive_asctime(),
|
||||
"description" => HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
|
||||
"description_html" => HTML.filter_tags(user.bio, User.html_filter_policy(for_user)),
|
||||
"description_html" => description_html,
|
||||
"favourites_count" => 0,
|
||||
"followers_count" => user_info[:follower_count],
|
||||
"following" => following,
|
||||
|
@ -248,7 +248,7 @@ test "it adds cool emoji" do
|
||||
text = "I love :firefox:"
|
||||
|
||||
expected_result =
|
||||
"I love <img height=\"32px\" width=\"32px\" alt=\"firefox\" title=\"firefox\" src=\"/emoji/Firefox.gif\" />"
|
||||
"I love <img class=\"emoji\" alt=\"firefox\" title=\"firefox\" src=\"/emoji/Firefox.gif\" />"
|
||||
|
||||
assert Formatter.emojify(text) == expected_result
|
||||
end
|
||||
@ -263,7 +263,7 @@ test "it does not add XSS emoji" do
|
||||
}
|
||||
|
||||
expected_result =
|
||||
"I love <img height=\"32px\" width=\"32px\" alt=\"\" title=\"\" src=\"https://placehold.it/1x1\" />"
|
||||
"I love <img class=\"emoji\" alt=\"\" title=\"\" src=\"https://placehold.it/1x1\" />"
|
||||
|
||||
assert Formatter.emojify(text, custom_emoji) == expected_result
|
||||
end
|
||||
|
@ -1103,7 +1103,7 @@ test "preserves hosts in user links text" do
|
||||
expected_text =
|
||||
"A.k.a. <span class='h-card'><a data-user='#{remote_user.id}' class='u-url mention' href='#{
|
||||
remote_user.ap_id
|
||||
}'>" <> "@<span>nick@domain.com</span></a></span>"
|
||||
}'>@<span>nick@domain.com</span></a></span>"
|
||||
|
||||
assert expected_text == User.parse_bio(bio, user)
|
||||
end
|
||||
|
@ -2351,6 +2351,33 @@ test "requires 'write' permission", %{conn: conn} do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "updates profile emojos", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
note = "*sips :blank:*"
|
||||
name = "I am :firefox:"
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"note" => note,
|
||||
"display_name" => name
|
||||
})
|
||||
|
||||
assert json_response(conn, 200)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> get("/api/v1/accounts/#{user.id}")
|
||||
|
||||
assert user = json_response(conn, 200)
|
||||
|
||||
assert user["note"] == note
|
||||
assert user["display_name"] == name
|
||||
assert [%{"shortcode" => "blank"}, %{"shortcode" => "firefox"}] = user["emojis"]
|
||||
end
|
||||
end
|
||||
|
||||
test "get instance information", %{conn: conn} do
|
||||
|
@ -1611,6 +1611,34 @@ test "it unlocks an account", %{conn: conn} do
|
||||
|
||||
assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
# Broken before the change to class="emoji" and non-<img/> in the DB
|
||||
@tag :skip
|
||||
test "it formats emojos", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> post("/api/account/update_profile.json", %{
|
||||
"bio" => "I love our :moominmamma:"
|
||||
})
|
||||
|
||||
assert response = json_response(conn, 200)
|
||||
|
||||
assert %{
|
||||
"description" => "I love our :moominmamma:",
|
||||
"description_html" =>
|
||||
~s{I love our <img class="emoji" alt="moominmamma" title="moominmamma" src="} <>
|
||||
_
|
||||
} = response
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> get("/api/users/show.json?user_id=#{user.nickname}")
|
||||
|
||||
assert response == json_response(conn, 200)
|
||||
end
|
||||
end
|
||||
|
||||
defp valid_user(_context) do
|
||||
|
@ -100,7 +100,7 @@ test "a create activity with a summary containing emoji" do
|
||||
expected = ":firefox: meow"
|
||||
|
||||
expected_html =
|
||||
"<img height=\"32px\" width=\"32px\" alt=\"firefox\" title=\"firefox\" src=\"http://localhost:4001/emoji/Firefox.gif\" /> meow"
|
||||
"<img class=\"emoji\" alt=\"firefox\" title=\"firefox\" src=\"http://localhost:4001/emoji/Firefox.gif\" /> meow"
|
||||
|
||||
assert result["summary"] == expected
|
||||
assert result["summary_html"] == expected_html
|
||||
|
@ -32,7 +32,7 @@ test "A user with an avatar object", %{user: user} do
|
||||
|
||||
test "A user with emoji in username" do
|
||||
expected =
|
||||
"<img height=\"32px\" width=\"32px\" alt=\"karjalanpiirakka\" title=\"karjalanpiirakka\" src=\"/file.png\" /> man"
|
||||
"<img class=\"emoji\" alt=\"karjalanpiirakka\" title=\"karjalanpiirakka\" src=\"/file.png\" /> man"
|
||||
|
||||
user =
|
||||
insert(:user, %{
|
||||
|
Loading…
Reference in New Issue
Block a user