Browse Source

Merge branch 'mark-converstation-as-read-on-new-direct-message' into 'develop'

Mastodon API / Conversations: Mark the conversation as read for the author when they send a new direct message

See merge request pleroma/pleroma!1853
merge-requests/1875/head
feld 4 years ago
parent
commit
6c82b6e3bf
7 changed files with 91 additions and 13 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +6
    -0
      lib/pleroma/conversation/participation.ex
  3. +17
    -6
      lib/pleroma/web/activity_pub/activity_pub.ex
  4. +34
    -1
      test/conversation/participation_test.exs
  5. +21
    -0
      test/web/activity_pub/activity_pub_test.exs
  6. +10
    -4
      test/web/mastodon_api/controllers/conversation_controller_test.exs
  7. +2
    -2
      test/web/mastodon_api/views/account_view_test.exs

+ 1
- 0
CHANGELOG.md View File

@@ -32,6 +32,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- MRF (Simple Policy): Also use `:accept`/`:reject` on the actors rather than only their activities
- OStatus: Extract RSS functionality
- Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`)
- Mastodon API: Mark the direct conversation as read for the author when they send a new direct message

### Fixed
- Mastodon API: Fix private and direct statuses not being filtered out from the public timeline for an authenticated user (`GET /api/v1/timelines/public`)


+ 6
- 0
lib/pleroma/conversation/participation.ex View File

@@ -48,6 +48,12 @@ defmodule Pleroma.Conversation.Participation do
|> validate_required([:read])
end

def mark_as_read(%User{} = user, %Conversation{} = conversation) do
with %__MODULE__{} = participation <- for_user_and_conversation(user, conversation) do
mark_as_read(participation)
end
end

def mark_as_read(participation) do
participation
|> read_cng(%{read: true})


+ 17
- 6
lib/pleroma/web/activity_pub/activity_pub.ex View File

@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
alias Pleroma.Activity.Ir.Topics
alias Pleroma.Config
alias Pleroma.Conversation
alias Pleroma.Conversation.Participation
alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Object.Containment
@@ -153,11 +154,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do

Notification.create_notifications(activity)

participations =
activity
|> Conversation.create_or_bump_for()
|> get_participations()

conversation = create_or_bump_conversation(activity, map["actor"])
participations = get_participations(conversation)
stream_out(activity)
stream_out_participations(participations)
{:ok, activity}
@@ -182,7 +180,20 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end

defp get_participations({:ok, %{participations: participations}}), do: participations
defp create_or_bump_conversation(activity, actor) do
with {:ok, conversation} <- Conversation.create_or_bump_for(activity),
%User{} = user <- User.get_cached_by_ap_id(actor),
Participation.mark_as_read(user, conversation) do
{:ok, conversation}
end
end

defp get_participations({:ok, conversation}) do
conversation
|> Repo.preload(:participations, force: true)
|> Map.get(:participations)
end

defp get_participations(_), do: []

def stream_out_participations(participations) do


+ 34
- 1
test/conversation/participation_test.exs View File

@@ -23,6 +23,39 @@ defmodule Pleroma.Conversation.ParticipationTest do
assert %Pleroma.Conversation{} = participation.conversation
end

test "for a new conversation or a reply, it doesn't mark the author's participation as unread" do
user = insert(:user)
other_user = insert(:user)

{:ok, _} =
CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})

user = User.get_cached_by_id(user.id)
other_user = User.get_cached_by_id(other_user.id)

[%{read: true}] = Participation.for_user(user)
[%{read: false} = participation] = Participation.for_user(other_user)

assert User.get_cached_by_id(user.id).info.unread_conversation_count == 0
assert User.get_cached_by_id(other_user.id).info.unread_conversation_count == 1

{:ok, _} =
CommonAPI.post(other_user, %{
"status" => "Hey @#{user.nickname}.",
"visibility" => "direct",
"in_reply_to_conversation_id" => participation.id
})

user = User.get_cached_by_id(user.id)
other_user = User.get_cached_by_id(other_user.id)

[%{read: false}] = Participation.for_user(user)
[%{read: true}] = Participation.for_user(other_user)

assert User.get_cached_by_id(user.id).info.unread_conversation_count == 1
assert User.get_cached_by_id(other_user.id).info.unread_conversation_count == 0
end

test "for a new conversation, it sets the recipents of the participation" do
user = insert(:user)
other_user = insert(:user)
@@ -32,7 +65,7 @@ defmodule Pleroma.Conversation.ParticipationTest do
CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})

user = User.get_cached_by_id(user.id)
other_user = User.get_cached_by_id(user.id)
other_user = User.get_cached_by_id(other_user.id)
[participation] = Participation.for_user(user)
participation = Pleroma.Repo.preload(participation, :recipients)



+ 21
- 0
test/web/activity_pub/activity_pub_test.exs View File

@@ -41,6 +41,27 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert called(Pleroma.Web.Streamer.stream("participation", participations))
end
end

test "streams them out on activity creation" do
user_one = insert(:user)
user_two = insert(:user)

with_mock Pleroma.Web.Streamer,
stream: fn _, _ -> nil end do
{:ok, activity} =
CommonAPI.post(user_one, %{
"status" => "@#{user_two.nickname}",
"visibility" => "direct"
})

conversation =
activity.data["context"]
|> Pleroma.Conversation.get_for_ap_id()
|> Repo.preload(participations: :user)

assert called(Pleroma.Web.Streamer.stream("participation", conversation.participations))
end
end
end

describe "fetching restricted by visibility" do


+ 10
- 4
test/web/mastodon_api/controllers/conversation_controller_test.exs View File

@@ -54,9 +54,9 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
assert user_two.id in account_ids
assert user_three.id in account_ids
assert is_binary(res_id)
assert unread == true
assert unread == false
assert res_last_status["id"] == direct.id
assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1
assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 0
end

test "updates the last_status on reply", %{conn: conn} do
@@ -95,19 +95,23 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
"visibility" => "direct"
})

assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 0
assert User.get_cached_by_id(user_two.id).info.unread_conversation_count == 1

[%{"id" => direct_conversation_id, "unread" => true}] =
conn
|> assign(:user, user_one)
|> assign(:user, user_two)
|> get("/api/v1/conversations")
|> json_response(200)

%{"unread" => false} =
conn
|> assign(:user, user_one)
|> assign(:user, user_two)
|> post("/api/v1/conversations/#{direct_conversation_id}/read")
|> json_response(200)

assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 0
assert User.get_cached_by_id(user_two.id).info.unread_conversation_count == 0

# The conversation is marked as unread on reply
{:ok, _} =
@@ -124,6 +128,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
|> json_response(200)

assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1
assert User.get_cached_by_id(user_two.id).info.unread_conversation_count == 0

# A reply doesn't increment the user's unread_conversation_count if the conversation is unread
{:ok, _} =
@@ -134,6 +139,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
})

assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1
assert User.get_cached_by_id(user_two.id).info.unread_conversation_count == 0
end

test "(vanilla) Mastodon frontend behaviour", %{conn: conn} do


+ 2
- 2
test/web/mastodon_api/views/account_view_test.exs View File

@@ -424,8 +424,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
other_user = insert(:user)

{:ok, _activity} =
CommonAPI.post(user, %{
"status" => "Hey @#{other_user.nickname}.",
CommonAPI.post(other_user, %{
"status" => "Hey @#{user.nickname}.",
"visibility" => "direct"
})



Loading…
Cancel
Save