feat: Withdraw follow request
This commit is contained in:
parent
f27dd6a9a7
commit
75421b7446
6 changed files with 129 additions and 28 deletions
13
README.md
13
README.md
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
- [x] Sending follow request
|
- [x] Sending follow request
|
||||||
- [x] View following list
|
- [x] View following list
|
||||||
- [ ] Withdrawing follow request
|
- [x] Withdrawing follow request
|
||||||
- [ ] Unfollowing
|
- [ ] Unfollowing
|
||||||
- [ ] Proactively check the outbox of newly-accepted follows
|
- [ ] Proactively check the outbox of newly-accepted follows
|
||||||
|
|
||||||
|
|
@ -45,12 +45,23 @@
|
||||||
- [ ] Displaying polls
|
- [ ] Displaying polls
|
||||||
- [ ] Voting in polls
|
- [ ] Voting in polls
|
||||||
|
|
||||||
|
## Individual Post Page
|
||||||
|
|
||||||
|
- [ ] Show post
|
||||||
|
- [ ] Show replies to post (chronological order)
|
||||||
|
|
||||||
## DMs
|
## DMs
|
||||||
|
|
||||||
- [ ] Receiving DMs
|
- [ ] Receiving DMs
|
||||||
- [ ] Replying to DMs
|
- [ ] Replying to DMs
|
||||||
- [ ] Sending new DMs
|
- [ ] Sending new DMs
|
||||||
|
|
||||||
|
## Notifications
|
||||||
|
|
||||||
|
- [ ] Like notifications
|
||||||
|
- [ ] Reply notifications
|
||||||
|
- [ ] Boost notifications
|
||||||
|
|
||||||
## Allowlist
|
## Allowlist
|
||||||
|
|
||||||
- [ ] Manage approved instance list
|
- [ ] Manage approved instance list
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
defmodule Postland.Follow do
|
defmodule Postland.Follow do
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
use Phoenix.VerifiedRoutes, endpoint: PostlandWeb.Endpoint, router: PostlandWeb.Router
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
|
@ -10,11 +11,18 @@ defmodule Postland.Follow do
|
||||||
field :confirmed_at, :naive_datetime
|
field :confirmed_at, :naive_datetime
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def id(follow) do
|
||||||
|
encoded_followee = Base.url_encode64(follow.followee, padding: false)
|
||||||
|
encoded_follower = Base.url_encode64(follow.follower, padding: false)
|
||||||
|
|
||||||
|
url(~p"/follows/#{encoded_followee}/#{encoded_follower}")
|
||||||
|
end
|
||||||
|
|
||||||
def changeset(follower, followee, confirmed \\ false) do
|
def changeset(follower, followee, confirmed \\ false) do
|
||||||
attrs = %{
|
attrs = %{
|
||||||
follower: follower,
|
follower: follower,
|
||||||
followee: followee,
|
followee: followee,
|
||||||
confirmed_at: (if confirmed, do: NaiveDateTime.utc_now())
|
confirmed_at: if(confirmed, do: NaiveDateTime.utc_now())
|
||||||
}
|
}
|
||||||
|
|
||||||
%__MODULE__{}
|
%__MODULE__{}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,40 @@ defmodule Postland.Follows do
|
||||||
|> Repo.transaction()
|
|> Repo.transaction()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def record_and_send_withdrawl(request) do
|
||||||
|
Multi.new()
|
||||||
|
|> Multi.delete(:delete, request)
|
||||||
|
|> Multi.run(:send_acceptance, fn _data, _repo ->
|
||||||
|
send_withdrawl(request)
|
||||||
|
end)
|
||||||
|
|> Repo.transaction()
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_withdrawl(request) do
|
||||||
|
{:ok, actor} = ActivityPub.fetch_actor(request.followee)
|
||||||
|
inbox = Map.get(actor, "inbox")
|
||||||
|
|
||||||
|
body =
|
||||||
|
%{
|
||||||
|
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||||
|
"type" => "Undo",
|
||||||
|
"actor" => Postland.my_actor_id(),
|
||||||
|
"object" => Follow.id(request)
|
||||||
|
}
|
||||||
|
|> Jason.encode!()
|
||||||
|
|
||||||
|
headers =
|
||||||
|
Headers.signing_headers(
|
||||||
|
"POST",
|
||||||
|
inbox,
|
||||||
|
body,
|
||||||
|
Postland.my_actor_id(),
|
||||||
|
Accounts.solo_user().private_key
|
||||||
|
)
|
||||||
|
|
||||||
|
Req.post(inbox, headers: headers, body: body)
|
||||||
|
end
|
||||||
|
|
||||||
def send_acceptance(request) do
|
def send_acceptance(request) do
|
||||||
{:ok, actor} = ActivityPub.fetch_actor(request.follower)
|
{:ok, actor} = ActivityPub.fetch_actor(request.follower)
|
||||||
inbox = Map.get(actor, "inbox")
|
inbox = Map.get(actor, "inbox")
|
||||||
|
|
|
||||||
|
|
@ -44,12 +44,22 @@ defmodule PostlandWeb.CoreComponents do
|
||||||
@<%= @account["preferredUsername"] %>@<%= @host %>
|
@<%= @account["preferredUsername"] %>@<%= @host %>
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
<p :if={@status == :following_pending} class="font-semibold text-violet-600">
|
||||||
|
Pending follow request.
|
||||||
|
</p>
|
||||||
<p class="text-gray-500 text-sm">
|
<p class="text-gray-500 text-sm">
|
||||||
<%= {:safe, Earmark.as_html!(@account["summary"] || "")} %>
|
<%= {:safe, Earmark.as_html!(@account["summary"] || "")} %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-grow text-right">
|
<div class="flex-grow text-right">
|
||||||
<.button disabled>Pending</.button>
|
<.button
|
||||||
|
:if={@status == :following_pending}
|
||||||
|
phx-click="withdraw"
|
||||||
|
phx-value-dom-id={@dom_id}
|
||||||
|
phx-value-id={@account["id"]}
|
||||||
|
>
|
||||||
|
Withdraw Request
|
||||||
|
</.button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
defmodule PostlandWeb.FollowingLive do
|
|
||||||
use PostlandWeb, :live_view
|
|
||||||
|
|
||||||
alias Postland.Actors
|
|
||||||
alias Postland.Follows
|
|
||||||
|
|
||||||
def render(assigns) do
|
|
||||||
~H"""
|
|
||||||
<div class="py-4">
|
|
||||||
<h3 class="text-base font-semibold">Following</h3>
|
|
||||||
<p :if={@accounts == []} class="text-gray-400">
|
|
||||||
You aren't following anyone.
|
|
||||||
</p>
|
|
||||||
<div :for={acct <- @accounts} class="mt-2">
|
|
||||||
<.profile_card account={acct} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
"""
|
|
||||||
end
|
|
||||||
|
|
||||||
def mount(_params, _session, socket) do
|
|
||||||
follows = Follows.all_following() |> Enum.map(fn follow -> Actors.actor(follow.followee) end)
|
|
||||||
{:ok, assign(socket, :accounts, follows)}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
63
lib/postland_web/live/following_live.ex
Normal file
63
lib/postland_web/live/following_live.ex
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
defmodule PostlandWeb.FollowingLive do
|
||||||
|
use PostlandWeb, :live_view
|
||||||
|
|
||||||
|
alias Postland.Actors
|
||||||
|
alias Postland.Follows
|
||||||
|
|
||||||
|
def render(assigns) do
|
||||||
|
~H"""
|
||||||
|
<div class="py-4">
|
||||||
|
<h3 class="text-base font-semibold">Following</h3>
|
||||||
|
<p :if={@count == 0} class="text-gray-400">
|
||||||
|
You aren't following anyone.
|
||||||
|
</p>
|
||||||
|
<div :for={{dom_id, %{confirmed: confirmed, account: acct}} <- @streams.accounts} class="mt-2">
|
||||||
|
<.profile_card
|
||||||
|
id={dom_id}
|
||||||
|
account={acct}
|
||||||
|
dom_id={dom_id}
|
||||||
|
status={if confirmed, do: :following_confirmed, else: :following_pending}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
def mount(_params, _session, socket) do
|
||||||
|
follows =
|
||||||
|
Follows.all_following()
|
||||||
|
|> Enum.map(fn follow ->
|
||||||
|
%{
|
||||||
|
id: follow.followee,
|
||||||
|
confirmed: !!follow.confirmed_at,
|
||||||
|
account: Actors.actor(follow.followee)
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
account_count = Enum.count(follows)
|
||||||
|
|
||||||
|
socket =
|
||||||
|
socket
|
||||||
|
|> stream(:accounts, follows)
|
||||||
|
|> assign(:count, account_count)
|
||||||
|
|
||||||
|
{:ok, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event("withdraw", %{"id" => id, "dom-id" => dom_id}, socket) do
|
||||||
|
request = Follows.get(Postland.my_actor_id(), id)
|
||||||
|
|
||||||
|
socket =
|
||||||
|
case Follows.record_and_send_withdrawl(request) do
|
||||||
|
{:ok, _} ->
|
||||||
|
socket
|
||||||
|
|> stream_delete_by_dom_id(:accounts, dom_id)
|
||||||
|
|> assign(:count, socket.assigns.count - 1)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
put_flash(socket, :error, "An unexpected error occurred.")
|
||||||
|
end
|
||||||
|
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Reference in a new issue