Merge remote-tracking branch 'origin/develop' into benchmark-finishing
[akkoma] / lib / pleroma / conversation / participation.ex
index 2a11f9069940d221aec41bb39d6f758fa4dd71aa..ab81f32173fd1a69694eed8aa39c1be0013843bc 100644 (file)
@@ -5,6 +5,7 @@
 defmodule Pleroma.Conversation.Participation do
   use Ecto.Schema
   alias Pleroma.Conversation
+  alias Pleroma.Conversation.Participation.RecipientShip
   alias Pleroma.Repo
   alias Pleroma.User
   alias Pleroma.Web.ActivityPub.ActivityPub
@@ -12,10 +13,13 @@ defmodule Pleroma.Conversation.Participation do
   import Ecto.Query
 
   schema "conversation_participations" do
-    belongs_to(:user, User, type: Pleroma.FlakeId)
+    belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
     belongs_to(:conversation, Conversation)
     field(:read, :boolean, default: false)
-    field(:last_activity_id, Pleroma.FlakeId, virtual: true)
+    field(:last_activity_id, FlakeId.Ecto.CompatType, virtual: true)
+
+    has_many(:recipient_ships, RecipientShip)
+    has_many(:recipients, through: [:recipient_ships, :user])
 
     timestamps()
   end
@@ -48,6 +52,15 @@ defmodule Pleroma.Conversation.Participation do
     participation
     |> read_cng(%{read: true})
     |> Repo.update()
+    |> case do
+      {:ok, participation} ->
+        participation = Repo.preload(participation, :user)
+        User.set_unread_conversation_count(participation.user)
+        {:ok, participation}
+
+      error ->
+        error
+    end
   end
 
   def mark_as_unread(participation) do
@@ -59,10 +72,18 @@ defmodule Pleroma.Conversation.Participation do
   def for_user(user, params \\ %{}) do
     from(p in __MODULE__,
       where: p.user_id == ^user.id,
-      order_by: [desc: p.updated_at]
+      order_by: [desc: p.updated_at],
+      preload: [conversation: [:users]]
     )
     |> Pleroma.Pagination.fetch_paginated(params)
-    |> Repo.preload(conversation: [:users])
+  end
+
+  def for_user_and_conversation(user, conversation) do
+    from(p in __MODULE__,
+      where: p.user_id == ^user.id,
+      where: p.conversation_id == ^conversation.id
+    )
+    |> Repo.one()
   end
 
   def for_user_with_last_activity_id(user, params \\ %{}) do
@@ -79,5 +100,56 @@ defmodule Pleroma.Conversation.Participation do
         | last_activity_id: activity_id
       }
     end)
+    |> Enum.filter(& &1.last_activity_id)
+  end
+
+  def get(_, _ \\ [])
+  def get(nil, _), do: nil
+
+  def get(id, params) do
+    query =
+      if preload = params[:preload] do
+        from(p in __MODULE__,
+          preload: ^preload
+        )
+      else
+        __MODULE__
+      end
+
+    Repo.get(query, id)
+  end
+
+  def set_recipients(participation, user_ids) do
+    user_ids =
+      [participation.user_id | user_ids]
+      |> Enum.uniq()
+
+    Repo.transaction(fn ->
+      query =
+        from(r in RecipientShip,
+          where: r.participation_id == ^participation.id
+        )
+
+      Repo.delete_all(query)
+
+      users =
+        from(u in User,
+          where: u.id in ^user_ids
+        )
+        |> Repo.all()
+
+      RecipientShip.create(users, participation)
+      :ok
+    end)
+
+    {:ok, Repo.preload(participation, :recipients, force: true)}
+  end
+
+  def unread_conversation_count_for_user(user) do
+    from(p in __MODULE__,
+      where: p.user_id == ^user.id,
+      where: not p.read,
+      select: %{count: count(p.id)}
+    )
   end
 end