Merge branch 'pin-chats' into 'develop'
Chats: pin/unpin chats See merge request pleroma/pleroma!3637
This commit is contained in:
commit
ca03d94f52
12 changed files with 191 additions and 17 deletions
1
changelog.d/pin-chats.fix
Normal file
1
changelog.d/pin-chats.fix
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Allow to pin/unpip chats
|
||||||
|
|
@ -66,9 +66,9 @@ Returned data:
|
||||||
"username": "somenick",
|
"username": "somenick",
|
||||||
...
|
...
|
||||||
},
|
},
|
||||||
"id" : "1",
|
"id": "1",
|
||||||
"unread" : 2,
|
"unread": 2,
|
||||||
"last_message" : {...}, // The last message in that chat
|
"last_message": {...}, // The last message in that chat
|
||||||
"updated_at": "2020-04-21T15:11:46.000Z"
|
"updated_at": "2020-04-21T15:11:46.000Z"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -93,8 +93,8 @@ Returned data:
|
||||||
"username": "somenick",
|
"username": "somenick",
|
||||||
...
|
...
|
||||||
},
|
},
|
||||||
"id" : "1",
|
"id": "1",
|
||||||
"unread" : 0,
|
"unread": 0,
|
||||||
"updated_at": "2020-04-21T15:11:46.000Z"
|
"updated_at": "2020-04-21T15:11:46.000Z"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -111,7 +111,7 @@ The modified chat message
|
||||||
|
|
||||||
### Getting a list of Chats
|
### Getting a list of Chats
|
||||||
|
|
||||||
`GET /api/v1/pleroma/chats`
|
`GET /api/v2/pleroma/chats`
|
||||||
|
|
||||||
This will return a list of chats that you have been involved in, sorted by their
|
This will return a list of chats that you have been involved in, sorted by their
|
||||||
last update (so new chats will be at the top).
|
last update (so new chats will be at the top).
|
||||||
|
|
@ -119,6 +119,7 @@ last update (so new chats will be at the top).
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
- with_muted: Include chats from muted users (boolean).
|
- with_muted: Include chats from muted users (boolean).
|
||||||
|
- pinned: Include only pinned chats (boolean).
|
||||||
|
|
||||||
Returned data:
|
Returned data:
|
||||||
|
|
||||||
|
|
@ -130,16 +131,16 @@ Returned data:
|
||||||
"username": "somenick",
|
"username": "somenick",
|
||||||
...
|
...
|
||||||
},
|
},
|
||||||
"id" : "1",
|
"id": "1",
|
||||||
"unread" : 2,
|
"unread": 2,
|
||||||
"last_message" : {...}, // The last message in that chat
|
"last_message": {...}, // The last message in that chat
|
||||||
"updated_at": "2020-04-21T15:11:46.000Z"
|
"updated_at": "2020-04-21T15:11:46.000Z"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
The recipient of messages that are sent to this chat is given by their AP ID.
|
The recipient of messages that are sent to this chat is given by their AP ID.
|
||||||
No pagination is implemented for now.
|
The usual pagination options are implemented.
|
||||||
|
|
||||||
### Getting the messages for a Chat
|
### Getting the messages for a Chat
|
||||||
|
|
||||||
|
|
@ -226,6 +227,32 @@ Deleting a chat message for given Chat id works like this:
|
||||||
|
|
||||||
Returned data is the deleted message.
|
Returned data is the deleted message.
|
||||||
|
|
||||||
|
### Pinning a chat
|
||||||
|
|
||||||
|
Pinning a chat works like this:
|
||||||
|
|
||||||
|
`POST /api/v1/pleroma/chats/:id/pin`
|
||||||
|
|
||||||
|
Returned data:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"id": "someflakeid",
|
||||||
|
"username": "somenick",
|
||||||
|
...
|
||||||
|
},
|
||||||
|
"id": "1",
|
||||||
|
"unread": 0,
|
||||||
|
"updated_at": "2020-04-21T15:11:46.000Z",
|
||||||
|
"pinned": true,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To unpin a pinned chat, use:
|
||||||
|
|
||||||
|
`POST /api/v1/pleroma/chats/:id/unpin`
|
||||||
|
|
||||||
### Notifications
|
### Notifications
|
||||||
|
|
||||||
There's a new `pleroma:chat_mention` notification, which has this form. It is not given out in the notifications endpoint by default, you need to explicitly request it with `include_types[]=pleroma:chat_mention`:
|
There's a new `pleroma:chat_mention` notification, which has this form. It is not given out in the notifications endpoint by default, you need to explicitly request it with `include_types[]=pleroma:chat_mention`:
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ defmodule Pleroma.Chat do
|
||||||
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
|
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
|
||||||
field(:recipient, :string)
|
field(:recipient, :string)
|
||||||
|
|
||||||
|
field(:pinned, :boolean)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -94,4 +96,16 @@ defmodule Pleroma.Chat do
|
||||||
order_by: [desc: c.updated_at]
|
order_by: [desc: c.updated_at]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pin(%__MODULE__{} = chat) do
|
||||||
|
chat
|
||||||
|
|> cast(%{pinned: true}, [:pinned])
|
||||||
|
|> Repo.update()
|
||||||
|
end
|
||||||
|
|
||||||
|
def unpin(%__MODULE__{} = chat) do
|
||||||
|
chat
|
||||||
|
|> cast(%{pinned: false}, [:pinned])
|
||||||
|
|> Repo.update()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
|
||||||
:query,
|
:query,
|
||||||
BooleanLike.schema(),
|
BooleanLike.schema(),
|
||||||
"Include chats from muted users"
|
"Include chats from muted users"
|
||||||
)
|
),
|
||||||
|
Operation.parameter(:pinned, :query, BooleanLike.schema(), "Include only pinned chats")
|
||||||
],
|
],
|
||||||
responses: %{
|
responses: %{
|
||||||
200 => Operation.response("The chats of the user", "application/json", chats_response())
|
200 => Operation.response("The chats of the user", "application/json", chats_response())
|
||||||
|
|
@ -166,7 +167,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
|
||||||
:query,
|
:query,
|
||||||
BooleanLike.schema(),
|
BooleanLike.schema(),
|
||||||
"Include chats from muted users"
|
"Include chats from muted users"
|
||||||
)
|
),
|
||||||
|
Operation.parameter(:pinned, :query, BooleanLike.schema(), "Include only pinned chats")
|
||||||
| pagination_params()
|
| pagination_params()
|
||||||
],
|
],
|
||||||
responses: %{
|
responses: %{
|
||||||
|
|
@ -257,6 +259,44 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pin_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Chats"],
|
||||||
|
summary: "Pin a chat",
|
||||||
|
operationId: "ChatController.pin",
|
||||||
|
parameters: [
|
||||||
|
Operation.parameter(:id, :path, :string, "The id of the chat", required: true)
|
||||||
|
],
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("The existing chat", "application/json", Chat)
|
||||||
|
},
|
||||||
|
security: [
|
||||||
|
%{
|
||||||
|
"oAuth" => ["write:chats"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def unpin_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Chats"],
|
||||||
|
summary: "Unpin a chat",
|
||||||
|
operationId: "ChatController.unpin",
|
||||||
|
parameters: [
|
||||||
|
Operation.parameter(:id, :path, :string, "The id of the chat", required: true)
|
||||||
|
],
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("The existing chat", "application/json", Chat)
|
||||||
|
},
|
||||||
|
security: [
|
||||||
|
%{
|
||||||
|
"oAuth" => ["write:chats"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def chats_response do
|
def chats_response do
|
||||||
%Schema{
|
%Schema{
|
||||||
title: "ChatsResponse",
|
title: "ChatsResponse",
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Chat do
|
||||||
account: %Schema{type: :object},
|
account: %Schema{type: :object},
|
||||||
unread: %Schema{type: :integer},
|
unread: %Schema{type: :integer},
|
||||||
last_message: ChatMessage,
|
last_message: ChatMessage,
|
||||||
updated_at: %Schema{type: :string, format: :"date-time"}
|
updated_at: %Schema{type: :string, format: :"date-time"},
|
||||||
|
pinned: %Schema{type: :boolean}
|
||||||
},
|
},
|
||||||
example: %{
|
example: %{
|
||||||
"account" => %{
|
"account" => %{
|
||||||
|
|
@ -69,7 +70,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Chat do
|
||||||
"id" => "1",
|
"id" => "1",
|
||||||
"unread" => 2,
|
"unread" => 2,
|
||||||
"last_message" => ChatMessage.schema().example,
|
"last_message" => ChatMessage.schema().example,
|
||||||
"updated_at" => "2020-04-21T15:06:45.000Z"
|
"updated_at" => "2020-04-21T15:06:45.000Z",
|
||||||
|
"pinned" => false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
|
||||||
"pleroma_emoji_reactions",
|
"pleroma_emoji_reactions",
|
||||||
"pleroma_custom_emoji_reactions",
|
"pleroma_custom_emoji_reactions",
|
||||||
"pleroma_chat_messages",
|
"pleroma_chat_messages",
|
||||||
|
"pleroma:pin_chats",
|
||||||
if Config.get([:instance, :show_reactions]) do
|
if Config.get([:instance, :show_reactions]) do
|
||||||
"exposable_reactions"
|
"exposable_reactions"
|
||||||
end,
|
end,
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,9 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
|
||||||
:create,
|
:create,
|
||||||
:mark_as_read,
|
:mark_as_read,
|
||||||
:mark_message_as_read,
|
:mark_message_as_read,
|
||||||
:delete_message
|
:delete_message,
|
||||||
|
:pin,
|
||||||
|
:unpin
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -199,8 +201,16 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
|
||||||
user_id
|
user_id
|
||||||
|> Chat.for_user_query()
|
|> Chat.for_user_query()
|
||||||
|> where([c], c.recipient not in ^exclude_users)
|
|> where([c], c.recipient not in ^exclude_users)
|
||||||
|
|> restrict_pinned(params)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp restrict_pinned(query, %{pinned: pinned}) when is_boolean(pinned) do
|
||||||
|
query
|
||||||
|
|> where([c], c.pinned == ^pinned)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp restrict_pinned(query, _), do: query
|
||||||
|
|
||||||
def create(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
|
def create(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
|
||||||
with %User{ap_id: recipient} <- User.get_cached_by_id(id),
|
with %User{ap_id: recipient} <- User.get_cached_by_id(id),
|
||||||
{:ok, %Chat{} = chat} <- Chat.get_or_create(user.id, recipient) do
|
{:ok, %Chat{} = chat} <- Chat.get_or_create(user.id, recipient) do
|
||||||
|
|
@ -214,6 +224,20 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pin(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
|
||||||
|
with {:ok, chat} <- Chat.get_by_user_and_id(user, id),
|
||||||
|
{:ok, chat} <- Chat.pin(chat) do
|
||||||
|
render(conn, "show.json", chat: chat)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def unpin(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
|
||||||
|
with {:ok, chat} <- Chat.get_by_user_and_id(user, id),
|
||||||
|
{:ok, chat} <- Chat.unpin(chat) do
|
||||||
|
render(conn, "show.json", chat: chat)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp idempotency_key(conn) do
|
defp idempotency_key(conn) do
|
||||||
case get_req_header(conn, "idempotency-key") do
|
case get_req_header(conn, "idempotency-key") do
|
||||||
[key] -> key
|
[key] -> key
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ defmodule Pleroma.Web.PleromaAPI.ChatView do
|
||||||
last_message:
|
last_message:
|
||||||
last_message &&
|
last_message &&
|
||||||
MessageReferenceView.render("show.json", chat_message_reference: last_message),
|
MessageReferenceView.render("show.json", chat_message_reference: last_message),
|
||||||
updated_at: Utils.to_masto_date(chat.updated_at)
|
updated_at: Utils.to_masto_date(chat.updated_at),
|
||||||
|
pinned: chat.pinned
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -581,6 +581,8 @@ defmodule Pleroma.Web.Router do
|
||||||
delete("/chats/:id/messages/:message_id", ChatController, :delete_message)
|
delete("/chats/:id/messages/:message_id", ChatController, :delete_message)
|
||||||
post("/chats/:id/read", ChatController, :mark_as_read)
|
post("/chats/:id/read", ChatController, :mark_as_read)
|
||||||
post("/chats/:id/messages/:message_id/read", ChatController, :mark_message_as_read)
|
post("/chats/:id/messages/:message_id/read", ChatController, :mark_message_as_read)
|
||||||
|
post("/chats/:id/pin", ChatController, :pin)
|
||||||
|
post("/chats/:id/unpin", ChatController, :unpin)
|
||||||
|
|
||||||
get("/conversations/:id/statuses", ConversationController, :statuses)
|
get("/conversations/:id/statuses", ConversationController, :statuses)
|
||||||
get("/conversations/:id", ConversationController, :show)
|
get("/conversations/:id", ConversationController, :show)
|
||||||
|
|
|
||||||
11
priv/repo/migrations/20220222203933_add_pinned_to_chats.exs
Normal file
11
priv/repo/migrations/20220222203933_add_pinned_to_chats.exs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.AddPinnedToChats do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
alter table(:chats) do
|
||||||
|
add(:pinned, :boolean, default: false, null: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
create(index(:chats, [:pinned]))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -337,6 +337,41 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "POST /api/v1/pleroma/chats/:id/pin" do
|
||||||
|
setup do: oauth_access(["write:chats"])
|
||||||
|
|
||||||
|
test "it pins a chat", %{conn: conn, user: user} do
|
||||||
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/pleroma/chats/#{chat.id}/pin")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert %{"pinned" => true} = result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "POST /api/v1/pleroma/chats/:id/unpin" do
|
||||||
|
setup do: oauth_access(["write:chats"])
|
||||||
|
|
||||||
|
test "it unpins a chat", %{conn: conn, user: user} do
|
||||||
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)
|
||||||
|
{:ok, chat} = Chat.pin(chat)
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/pleroma/chats/#{chat.id}/unpin")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert %{"pinned" => false} = result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for tested_endpoint <- ["/api/v1/pleroma/chats", "/api/v2/pleroma/chats"] do
|
for tested_endpoint <- ["/api/v1/pleroma/chats", "/api/v2/pleroma/chats"] do
|
||||||
describe "GET #{tested_endpoint}" do
|
describe "GET #{tested_endpoint}" do
|
||||||
setup do: oauth_access(["read:chats"])
|
setup do: oauth_access(["read:chats"])
|
||||||
|
|
@ -407,6 +442,21 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
|
||||||
assert length(result) == 1
|
assert length(result) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it only returns pinned chats", %{conn: conn, user: user} do
|
||||||
|
recipient1 = insert(:user)
|
||||||
|
recipient2 = insert(:user)
|
||||||
|
|
||||||
|
{:ok, %{id: id} = chat} = Chat.get_or_create(user.id, recipient1.ap_id)
|
||||||
|
{:ok, _} = Chat.get_or_create(user.id, recipient2.ap_id)
|
||||||
|
|
||||||
|
Chat.pin(chat)
|
||||||
|
|
||||||
|
[%{"id" => ^id, "pinned" => true}] =
|
||||||
|
conn
|
||||||
|
|> get("#{unquote(tested_endpoint)}?pinned=true")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
end
|
||||||
|
|
||||||
if tested_endpoint == "/api/v1/pleroma/chats" do
|
if tested_endpoint == "/api/v1/pleroma/chats" do
|
||||||
test "it returns all chats", %{conn: conn, user: user} do
|
test "it returns all chats", %{conn: conn, user: user} do
|
||||||
Enum.each(1..30, fn _ ->
|
Enum.each(1..30, fn _ ->
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,8 @@ defmodule Pleroma.Web.PleromaAPI.ChatViewTest do
|
||||||
AccountView.render("show.json", user: recipient, skip_visibility_check: true),
|
AccountView.render("show.json", user: recipient, skip_visibility_check: true),
|
||||||
unread: 0,
|
unread: 0,
|
||||||
last_message: nil,
|
last_message: nil,
|
||||||
updated_at: Utils.to_masto_date(chat.updated_at)
|
updated_at: Utils.to_masto_date(chat.updated_at),
|
||||||
|
pinned: false
|
||||||
}
|
}
|
||||||
|
|
||||||
{:ok, chat_message_creation} = CommonAPI.post_chat_message(user, recipient, "hello")
|
{:ok, chat_message_creation} = CommonAPI.post_chat_message(user, recipient, "hello")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue