Merge branch 'conversation-pagination' into 'develop'

Conversation pagination

See merge request pleroma/pleroma!2601
This commit is contained in:
lain 2020-05-30 10:02:37 +00:00
commit b004c427a0
2 changed files with 100 additions and 82 deletions

View File

@ -21,6 +21,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationController do
@doc "GET /api/v1/conversations" @doc "GET /api/v1/conversations"
def index(%{assigns: %{user: user}} = conn, params) do def index(%{assigns: %{user: user}} = conn, params) do
params = stringify_pagination_params(params)
participations = Participation.for_user_with_last_activity_id(user, params) participations = Participation.for_user_with_last_activity_id(user, params)
conn conn
@ -36,4 +37,20 @@ def mark_as_read(%{assigns: %{user: user}} = conn, %{id: participation_id}) do
render(conn, "participation.json", participation: participation, for: user) render(conn, "participation.json", participation: participation, for: user)
end end
end end
defp stringify_pagination_params(params) do
atom_keys =
Pleroma.Pagination.page_keys()
|> Enum.map(&String.to_atom(&1))
str_keys =
params
|> Map.take(atom_keys)
|> Enum.map(fn {key, value} -> {to_string(key), value} end)
|> Enum.into(%{})
params
|> Map.delete(atom_keys)
|> Map.merge(str_keys)
end
end end

View File

@ -12,84 +12,88 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
setup do: oauth_access(["read:statuses"]) setup do: oauth_access(["read:statuses"])
test "returns a list of conversations", %{user: user_one, conn: conn} do describe "returns a list of conversations" do
user_two = insert(:user) setup(%{user: user_one, conn: conn}) do
user_three = insert(:user) user_two = insert(:user)
user_three = insert(:user)
{:ok, user_two} = User.follow(user_two, user_one) {:ok, user_two} = User.follow(user_two, user_one)
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0 {:ok, %{user: user_one, user_two: user_two, user_three: user_three, conn: conn}}
end
{:ok, direct} = test "returns correct conversations", %{
CommonAPI.post(user_one, %{ user: user_one,
status: "Hi @#{user_two.nickname}, @#{user_three.nickname}!", user_two: user_two,
visibility: "direct" user_three: user_three,
}) conn: conn
} do
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0
{:ok, direct} = create_direct_message(user_one, [user_two, user_three])
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1 assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1
{:ok, _follower_only} = {:ok, _follower_only} =
CommonAPI.post(user_one, %{ CommonAPI.post(user_one, %{
status: "Hi @#{user_two.nickname}!", status: "Hi @#{user_two.nickname}!",
visibility: "private" visibility: "private"
}) })
res_conn = get(conn, "/api/v1/conversations") res_conn = get(conn, "/api/v1/conversations")
assert response = json_response_and_validate_schema(res_conn, 200) assert response = json_response_and_validate_schema(res_conn, 200)
assert [ assert [
%{ %{
"id" => res_id, "id" => res_id,
"accounts" => res_accounts, "accounts" => res_accounts,
"last_status" => res_last_status, "last_status" => res_last_status,
"unread" => unread "unread" => unread
} }
] = response ] = response
account_ids = Enum.map(res_accounts, & &1["id"]) account_ids = Enum.map(res_accounts, & &1["id"])
assert length(res_accounts) == 2 assert length(res_accounts) == 2
assert user_two.id in account_ids assert user_two.id in account_ids
assert user_three.id in account_ids assert user_three.id in account_ids
assert is_binary(res_id) assert is_binary(res_id)
assert unread == false assert unread == false
assert res_last_status["id"] == direct.id assert res_last_status["id"] == direct.id
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0 assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0
end
test "observes limit params", %{
user: user_one,
user_two: user_two,
user_three: user_three,
conn: conn
} do
{:ok, _} = create_direct_message(user_one, [user_two, user_three])
{:ok, _} = create_direct_message(user_two, [user_one, user_three])
{:ok, _} = create_direct_message(user_three, [user_two, user_one])
res_conn = get(conn, "/api/v1/conversations?limit=1")
assert response = json_response_and_validate_schema(res_conn, 200)
assert Enum.count(response) == 1
res_conn = get(conn, "/api/v1/conversations?limit=2")
assert response = json_response_and_validate_schema(res_conn, 200)
assert Enum.count(response) == 2
end
end end
test "filters conversations by recipients", %{user: user_one, conn: conn} do test "filters conversations by recipients", %{user: user_one, conn: conn} do
user_two = insert(:user) user_two = insert(:user)
user_three = insert(:user) user_three = insert(:user)
{:ok, direct1} = create_direct_message(user_one, [user_two])
{:ok, direct1} = {:ok, _direct2} = create_direct_message(user_one, [user_three])
CommonAPI.post(user_one, %{ {:ok, direct3} = create_direct_message(user_one, [user_two, user_three])
status: "Hi @#{user_two.nickname}!", {:ok, _direct4} = create_direct_message(user_two, [user_three])
visibility: "direct" {:ok, direct5} = create_direct_message(user_two, [user_one])
})
{:ok, _direct2} =
CommonAPI.post(user_one, %{
status: "Hi @#{user_three.nickname}!",
visibility: "direct"
})
{:ok, direct3} =
CommonAPI.post(user_one, %{
status: "Hi @#{user_two.nickname}, @#{user_three.nickname}!",
visibility: "direct"
})
{:ok, _direct4} =
CommonAPI.post(user_two, %{
status: "Hi @#{user_three.nickname}!",
visibility: "direct"
})
{:ok, direct5} =
CommonAPI.post(user_two, %{
status: "Hi @#{user_one.nickname}!",
visibility: "direct"
})
assert [conversation1, conversation2] = assert [conversation1, conversation2] =
conn conn
@ -109,12 +113,7 @@ test "filters conversations by recipients", %{user: user_one, conn: conn} do
test "updates the last_status on reply", %{user: user_one, conn: conn} do test "updates the last_status on reply", %{user: user_one, conn: conn} do
user_two = insert(:user) user_two = insert(:user)
{:ok, direct} = create_direct_message(user_one, [user_two])
{:ok, direct} =
CommonAPI.post(user_one, %{
status: "Hi @#{user_two.nickname}",
visibility: "direct"
})
{:ok, direct_reply} = {:ok, direct_reply} =
CommonAPI.post(user_two, %{ CommonAPI.post(user_two, %{
@ -133,12 +132,7 @@ test "updates the last_status on reply", %{user: user_one, conn: conn} do
test "the user marks a conversation as read", %{user: user_one, conn: conn} do test "the user marks a conversation as read", %{user: user_one, conn: conn} do
user_two = insert(:user) user_two = insert(:user)
{:ok, direct} = create_direct_message(user_one, [user_two])
{:ok, direct} =
CommonAPI.post(user_one, %{
status: "Hi @#{user_two.nickname}",
visibility: "direct"
})
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0 assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1 assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1
@ -194,15 +188,22 @@ test "the user marks a conversation as read", %{user: user_one, conn: conn} do
test "(vanilla) Mastodon frontend behaviour", %{user: user_one, conn: conn} do test "(vanilla) Mastodon frontend behaviour", %{user: user_one, conn: conn} do
user_two = insert(:user) user_two = insert(:user)
{:ok, direct} = create_direct_message(user_one, [user_two])
{:ok, direct} =
CommonAPI.post(user_one, %{
status: "Hi @#{user_two.nickname}!",
visibility: "direct"
})
res_conn = get(conn, "/api/v1/statuses/#{direct.id}/context") res_conn = get(conn, "/api/v1/statuses/#{direct.id}/context")
assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200) assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200)
end end
defp create_direct_message(sender, recips) do
hellos =
recips
|> Enum.map(fn s -> "@#{s.nickname}" end)
|> Enum.join(", ")
CommonAPI.post(sender, %{
status: "Hi #{hellos}!",
visibility: "direct"
})
end
end end