UI: Remote actor view + follow UI

This commit is contained in:
Pere Lev 2024-04-28 21:08:04 +03:00
parent a428bd74ab
commit 6cdd332d1d
No known key found for this signature in database
GPG key ID: 5252C5C863E5E57D
20 changed files with 375 additions and 62 deletions

View file

@ -20,7 +20,7 @@ module Vervis.Client
, comment , comment
--, createThread --, createThread
--, createReply --, createReply
--, follow , follow
--, followSharer --, followSharer
--, followProject --, followProject
--, followTicket --, followTicket
@ -28,6 +28,7 @@ module Vervis.Client
, offerIssue , offerIssue
, resolve , resolve
, unresolve , unresolve
, unfollow
--, undoFollowSharer --, undoFollowSharer
--, undoFollowProject --, undoFollowProject
--, undoFollowTicket --, undoFollowTicket
@ -240,37 +241,35 @@ createReply shrAuthor (TextPandocMarkdown msg) hDest recipsA recipsC context mid
, noteContent = contentHtml , noteContent = contentHtml
} }
-} -}
-}
follow follow
:: (MonadHandler m, HandlerSite m ~ App) :: PersonId
=> ShrIdent -> ObjURI URIMode -> ObjURI URIMode -> Bool -> m (TextHtml, Audience URIMode, AP.Follow URIMode) -> FedURI
follow shrAuthor uObject@(ObjURI hObject luObject) uRecip hide = do -> ExceptT Text Handler (Maybe HTML, [Aud URIMode], AP.Follow URIMode)
error "Temporarily disabled" follow personID uActor = do
{- let activity = AP.Follow
summary <- { followObject = uActor
TextHtml . TL.toStrict . renderHtml <$> , followContext = Nothing
withUrlRenderer , followHide = False
[hamlet|
<p>
<a href=@{SharerR shrAuthor}>
#{shr2text shrAuthor}
\ requested to follow #
<a href=#{renderObjURI uObject}>
#{renderAuthority hObject}#{localUriPath luObject}
\.
|]
let followAP = AP.Follow
{ followObject = uObject
, followContext =
if uObject == uRecip
then Nothing
else Just uRecip
, followHide = hide
} }
audience = Audience [uRecip] [] [] [] [] []
return (summary, audience, followAP)
-}
senderHash <- encodeKeyHashid personID
target <- do
u <- parseFedURIOld uActor
bitraverse parseLocalActorE pure u
audActor <-
case target of
Left la -> do
lah <- VR.hashLocalActor la
return $ AudLocal [lah] []
Right (ObjURI h lu) -> pure $ AudRemote h [lu] []
let audience = [audActor]
return (Nothing, audience, activity)
{-
followSharer followSharer
:: (MonadHandler m, HandlerSite m ~ App, MonadSite m, SiteEnv m ~ App) :: (MonadHandler m, HandlerSite m ~ App, MonadSite m, SiteEnv m ~ App)
=> ShrIdent -> ShrIdent -> Bool -> m (TextHtml, Audience URIMode, AP.Follow URIMode) => ShrIdent -> ShrIdent -> Bool -> m (TextHtml, Audience URIMode, AP.Follow URIMode)
@ -545,6 +544,42 @@ unresolve senderHash uTicket = do
return (Nothing, audience, AP.Undo uResolve) return (Nothing, audience, AP.Undo uResolve)
unfollow
:: PersonId
-> FedURI
-> ExceptT Text Handler (Maybe HTML, [Aud URIMode], AP.Undo URIMode)
unfollow personID uActor = do
encodeRouteHome <- getEncodeRouteHome
senderHash <- encodeKeyHashid personID
target <- do
u <- parseFedURIOld uActor
bitraverse parseLocalActorE pure u
followID <- runDBExcept $ do
meActorID <- lift $ personActor <$> getJust personID
case target of
Left byk -> do
themActorID <- localActorID <$> getLocalActorEntityE byk "No such local acto in DB"
theirFollowerSetID <- lift $ actorFollowers <$> getJust themActorID
mf <- lift $ getValBy $ UniqueFollow meActorID theirFollowerSetID
followFollow <$>
fromMaybeE mf "I don't have a record of following this local actor, so idk which Follow activity to Undo"
Right u -> do
mf <- lift $ getValBy $ UniqueFollowRemote meActorID u
followRemoteFollow <$>
fromMaybeE mf "I don't have a record of following this remote actor, so idk which Follow activity to Undo"
uFollow <-
encodeRouteHome . PersonOutboxItemR senderHash <$> encodeKeyHashid followID
audActor <-
case target of
Left la -> do
lah <- VR.hashLocalActor la
return $ AudLocal [lah] []
Right (ObjURI h lu) -> pure $ AudRemote h [lu] []
let audience = [audActor]
return (Nothing, audience, AP.Undo uFollow)
{- {-
undoFollow undoFollow
:: (MonadUnliftIO m, MonadHandler m, HandlerSite m ~ App, MonadSite m, SiteEnv m ~ App) :: (MonadUnliftIO m, MonadHandler m, HandlerSite m ~ App, MonadSite m, SiteEnv m ~ App)

View file

@ -876,9 +876,6 @@ instance YesodBreadcrumbs App where
PersonMessageR p m -> ("Message #" <> keyHashidText m, Just $ PersonR p) PersonMessageR p m -> ("Message #" <> keyHashidText m, Just $ PersonR p)
PersonFollowR _ -> ("", Nothing)
PersonUnfollowR _ -> ("", Nothing)
PersonStampR p k -> ("Stamp #" <> keyHashidText k, Just $ PersonR p) PersonStampR p k -> ("Stamp #" <> keyHashidText k, Just $ PersonR p)
GroupNewR -> ("New Team", Just HomeR) GroupNewR -> ("New Team", Just HomeR)
@ -1055,3 +1052,11 @@ instance YesodBreadcrumbs App where
RepoErrboxR r -> ("Errbox", Just $ RepoR r) RepoErrboxR r -> ("Errbox", Just $ RepoR r)
DeckErrboxR d -> ("Errbox", Just $ DeckR d) DeckErrboxR d -> ("Errbox", Just $ DeckR d)
LoomErrboxR l -> ("Errbox", Just $ LoomR l) LoomErrboxR l -> ("Errbox", Just $ LoomR l)
RemoteActorsR -> ("Remote Actors", Just HomeR)
RemoteActorR k -> (T.pack $ show $ fromSqlKey k, Just RemoteActorsR)
FollowLocalR _ -> ("", Nothing)
FollowRemoteR _ -> ("", Nothing)
UnfollowLocalR _ -> ("", Nothing)
UnfollowRemoteR _ -> ("", Nothing)

View file

@ -52,6 +52,14 @@ module Vervis.Handler.Client
, postPublishResolveR , postPublishResolveR
, postAcceptInviteR , postAcceptInviteR
, getRemoteActorsR
, getRemoteActorR
, postFollowLocalR
, postFollowRemoteR
, postUnfollowLocalR
, postUnfollowRemoteR
) )
where where
@ -118,6 +126,7 @@ import Vervis.Recipient
import Vervis.Settings import Vervis.Settings
import Vervis.Web.Actor import Vervis.Web.Actor
import Vervis.Widget import Vervis.Widget
import Vervis.Widget.Person
import Vervis.Widget.Tracker import Vervis.Widget.Tracker
import qualified Vervis.Client as C import qualified Vervis.Client as C
@ -1694,3 +1703,139 @@ postAcceptInviteR fulfillsHash = do
Left e -> setMessage $ toHtml e Left e -> setMessage $ toHtml e
Right _acceptID -> setMessage "Accept sent" Right _acceptID -> setMessage "Accept sent"
redirect HomeR redirect HomeR
getRemoteActorsR :: Handler Html
getRemoteActorsR = do
actors <- runDB $ E.select $ E.from $ \ (actor `E.InnerJoin` object `E.InnerJoin` inztance) -> do
E.on $ object E.^. RemoteObjectInstance E.==. inztance E.^. InstanceId
E.on $ actor E.^. RemoteActorIdent E.==. object E.^. RemoteObjectId
E.orderBy [E.desc $ actor E.^. RemoteActorId]
return
( inztance
, object
, actor
)
defaultLayout $(widgetFile "remote-actors")
getRemoteActorR :: RemoteActorId -> Handler Html
getRemoteActorR actorID = do
maybePersonID <- maybeAuthId
(linkInfo@(Instance h, RemoteObject _ lu, RemoteActor _ _ luInbox mluFollowers errorSince typ), maybePermits) <- runDB $ do
actor <- get404 actorID
linkInfo <- do
object <- getJust $ remoteActorIdent actor
inztance <- getJust $ remoteObjectInstance object
return (inztance, object, actor)
maybePermits <-
for maybePersonID $ \ personID ->
getPermitsForResource personID $ Right actorID
return (linkInfo, maybePermits)
defaultLayout $(widgetFile "remote-actor")
postFollowLocalR :: ActorId -> Handler ()
postFollowLocalR actorID = do
personEntity@(Entity personID person) <- requireAuth
personHash <- encodeKeyHashid personID
encodeRouteHome <- getEncodeRouteHome
result <- runExceptT $ do
byk <- lift $ runDB $ do
_ <- get404 actorID
getLocalActor actorID
(actorR, uActor) <- lift $ do
byh <- VR.hashLocalActor byk
let actorR = renderLocalActor byh
return (actorR, encodeRouteHome actorR)
(maybeSummary, audience, follow) <- C.follow personID uActor
(localRecips, remoteRecips, fwdHosts, action) <-
C.makeServerInput Nothing maybeSummary audience $
AP.FollowActivity follow
(actorR,) <$>
handleViaActor
personID Nothing localRecips remoteRecips fwdHosts action
case result of
Left e -> do
setMessage $ toHtml e
redirect HomeR
Right (actorR, _followID) -> do
setMessage "Follow sent"
redirect actorR
postFollowRemoteR :: RemoteActorId -> Handler ()
postFollowRemoteR actorID = do
personEntity@(Entity personID person) <- requireAuth
personHash <- encodeKeyHashid personID
result <- runExceptT $ do
uActor <- lift $ runDB $ do
actor <- get404 actorID
getRemoteActorURI actor
(maybeSummary, audience, follow) <- C.follow personID uActor
(localRecips, remoteRecips, fwdHosts, action) <-
C.makeServerInput Nothing maybeSummary audience $
AP.FollowActivity follow
handleViaActor
personID Nothing localRecips remoteRecips fwdHosts action
case result of
Left e -> do
setMessage $ toHtml e
redirect HomeR
Right _followID -> do
setMessage "Follow sent"
redirect $ RemoteActorR actorID
postUnfollowLocalR :: ActorId -> Handler ()
postUnfollowLocalR actorID = do
personEntity@(Entity personID person) <- requireAuth
personHash <- encodeKeyHashid personID
encodeRouteHome <- getEncodeRouteHome
result <- runExceptT $ do
byk <- lift $ runDB $ do
_ <- get404 actorID
getLocalActor actorID
(actorR, uActor) <- lift $ do
byh <- VR.hashLocalActor byk
let actorR = renderLocalActor byh
return (actorR, encodeRouteHome actorR)
(maybeSummary, audience, undo) <- C.unfollow personID uActor
(localRecips, remoteRecips, fwdHosts, action) <-
C.makeServerInput Nothing maybeSummary audience $
AP.UndoActivity undo
(actorR,) <$>
handleViaActor
personID Nothing localRecips remoteRecips fwdHosts action
case result of
Left e -> do
setMessage $ toHtml e
redirect HomeR
Right (actorR, _undoID) -> do
setMessage "Undo sent"
redirect actorR
postUnfollowRemoteR :: RemoteActorId -> Handler ()
postUnfollowRemoteR actorID = do
personEntity@(Entity personID person) <- requireAuth
personHash <- encodeKeyHashid personID
result <- runExceptT $ do
uActor <- lift $ runDB $ do
actor <- get404 actorID
getRemoteActorURI actor
(maybeSummary, audience, undo) <- C.unfollow personID uActor
(localRecips, remoteRecips, fwdHosts, action) <-
C.makeServerInput Nothing maybeSummary audience $
AP.UndoActivity undo
handleViaActor
personID Nothing localRecips remoteRecips fwdHosts action
case result of
Left e -> do
setMessage $ toHtml e
redirect HomeR
Right _undoID -> do
setMessage "Undo sent"
redirect $ RemoteActorR actorID

View file

@ -94,6 +94,7 @@ import Vervis.Settings
import Vervis.Ticket import Vervis.Ticket
import Vervis.TicketFilter import Vervis.TicketFilter
import Vervis.Web.Actor import Vervis.Web.Actor
import Vervis.Widget.Person
import Vervis.Widget.Ticket import Vervis.Widget.Ticket
import Vervis.Widget.Tracker import Vervis.Widget.Tracker

View file

@ -1,6 +1,6 @@
{- This file is part of Vervis. {- This file is part of Vervis.
- -
- Written in 2016, 2018, 2019, 2022, 2023 - Written in 2016, 2018, 2019, 2022, 2023, 2024
- by fr33domlover <fr33domlover@riseup.net>. - by fr33domlover <fr33domlover@riseup.net>.
- -
- Copying is an act of love. Please copy, reuse and share. - Copying is an act of love. Please copy, reuse and share.
@ -27,9 +27,6 @@ module Vervis.Handler.Person
, getSshKeyR , getSshKeyR
, getPersonMessageR , getPersonMessageR
, postPersonFollowR
, postPersonUnfollowR
, getPersonStampR , getPersonStampR
) )
where where
@ -127,11 +124,6 @@ getPersonR personHash = do
, AP.actorSummary = Just $ actorDesc actor , AP.actorSummary = Just $ actorDesc actor
} }
} }
followButton =
followW
(PersonFollowR personHash)
(PersonUnfollowR personHash)
(actorFollowers actor)
let ep = Entity personID person let ep = Entity personID person
secure <- getSecure secure <- getSecure
@ -301,11 +293,5 @@ getPersonMessageR
getPersonMessageR personHash localMessageHash = getPersonMessageR personHash localMessageHash =
serveMessage personHash localMessageHash serveMessage personHash localMessageHash
postPersonFollowR :: KeyHashid Person -> Handler ()
postPersonFollowR _ = error "Temporarily disabled"
postPersonUnfollowR :: KeyHashid Person -> Handler ()
postPersonUnfollowR _ = error "Temporarily disabled"
getPersonStampR :: KeyHashid Person -> KeyHashid SigKey -> Handler TypedContent getPersonStampR :: KeyHashid Person -> KeyHashid SigKey -> Handler TypedContent
getPersonStampR = servePerActorKey personActor LocalActorPerson getPersonStampR = servePerActorKey personActor LocalActorPerson

View file

@ -1,6 +1,6 @@
{- This file is part of Vervis. {- This file is part of Vervis.
- -
- Written in 2016, 2018, 2019, 2020, 2022 - Written in 2016, 2018, 2019, 2020, 2022, 2024
- by fr33domlover <fr33domlover@riseup.net>. - by fr33domlover <fr33domlover@riseup.net>.
- -
- Copying is an act of love. Please copy, reuse and share. - Copying is an act of love. Please copy, reuse and share.
@ -112,9 +112,6 @@ getDarcsRepoSource repository actor repo dir loomIDs = do
Just s -> return s Just s -> return s
addStylesheet $ HighlightStyleR style addStylesheet $ HighlightStyleR style
$(widgetFile "repo/source-darcs") $(widgetFile "repo/source-darcs")
where
followButton =
followW (RepoFollowR repo) (RepoUnfollowR repo) (actorFollowers actor)
getDarcsRepoChanges :: KeyHashid Repo -> Handler TypedContent getDarcsRepoChanges :: KeyHashid Repo -> Handler TypedContent
getDarcsRepoChanges repo = do getDarcsRepoChanges repo = do

View file

@ -127,9 +127,6 @@ getGitRepoSource repository actor repo ref dir loomIDs = do
Just s -> return s Just s -> return s
addStylesheet $ HighlightStyleR style addStylesheet $ HighlightStyleR style
$(widgetFile "repo/source-git") $(widgetFile "repo/source-git")
where
followButton =
followW (RepoFollowR repo) (RepoUnfollowR repo) (actorFollowers actor)
{- {-
getGitRepoBranch :: ShrIdent -> RpIdent -> Text -> Handler TypedContent getGitRepoBranch :: ShrIdent -> RpIdent -> Text -> Handler TypedContent

View file

@ -1,6 +1,7 @@
{- This file is part of Vervis. {- This file is part of Vervis.
- -
- Written in 2016, 2019, 2022, 2023 by fr33domlover <fr33domlover@riseup.net>. - Written in 2016, 2019, 2022, 2023, 2024
- by fr33domlover <fr33domlover@riseup.net>.
- -
- Copying is an act of love. Please copy, reuse and share. - Copying is an act of love. Please copy, reuse and share.
- -
@ -17,11 +18,13 @@ module Vervis.Widget.Person
( personLinkW ( personLinkW
, personLinkFedW , personLinkFedW
, followW , followW
, followW'
, personNavW , personNavW
) )
where where
import Data.Foldable import Data.Foldable
import Data.Maybe
import Database.Persist import Database.Persist
import Network.HTTP.Types.Method import Network.HTTP.Types.Method
import Yesod.Core import Yesod.Core
@ -38,6 +41,7 @@ import Database.Persist.Local
import Vervis.Foundation import Vervis.Foundation
import Vervis.Model import Vervis.Model
import Vervis.Model.Ident import Vervis.Model.Ident
import Vervis.Persist.Actor
import Vervis.Settings import Vervis.Settings
import Vervis.Widget import Vervis.Widget
@ -84,6 +88,63 @@ followW followRoute unfollowRoute fsid = do
Nothing -> buttonW POST "Follow" followRoute Nothing -> buttonW POST "Follow" followRoute
Just _ -> buttonW POST "Unfollow" unfollowRoute Just _ -> buttonW POST "Unfollow" unfollowRoute
followW' :: Either ActorId RemoteActorId -> Widget
followW' (Left actorID) = do
maybeUser <- maybeVerifiedAuth
for_ maybeUser $ \ (Entity userID user) -> do
(alreadyFollowing, alreadyRequest) <-
handlerToWidget $ runDB $ do
fsid <- actorFollowers <$> getJust actorID
(,) <$> (isJust <$> getBy (UniqueFollow (personActor user) fsid))
<*> (isJust <$> getBy (UniqueFollowRequest (personActor user) fsid))
if alreadyFollowing
then
[whamlet|
<button type="button" disabled>
Following
^{buttonW POST "Unfollow" (UnfollowLocalR actorID)}
|]
else if alreadyRequest
then
[whamlet|
<button type="button" disabled>
Follow requested
|]
else
[whamlet|
<button type="button" disabled>
Not following
^{buttonW POST "Follow" (FollowLocalR actorID)}
|]
followW' (Right actorID) = do
maybeUser <- maybeVerifiedAuth
for_ maybeUser $ \ (Entity userID user) -> do
(alreadyFollowing, alreadyRequest) <-
handlerToWidget $ runDB $ do
a <- getJust actorID
u <- getRemoteActorURI a
(,) <$> (isJust <$> getBy (UniqueFollowRemote (personActor user) u))
<*> (isJust <$> getBy (UniqueFollowRemoteRequest userID u))
if alreadyFollowing
then
[whamlet|
<button type="button" disabled>
Following
^{buttonW POST "Unfollow" (UnfollowRemoteR actorID)}
|]
else if alreadyRequest
then
[whamlet|
<button type="button" disabled>
Follow requested
|]
else
[whamlet|
<button type="button" disabled>
Not following
^{buttonW POST "Follow" (FollowRemoteR actorID)}
|]
personNavW :: Entity Person -> Widget personNavW :: Entity Person -> Widget
personNavW (Entity personID person) = do personNavW (Entity personID person) = do
personHash <- encodeKeyHashid personID personHash <- encodeKeyHashid personID

View file

@ -38,6 +38,8 @@ import Yesod.Hashids
import qualified Web.ActivityPub as AP import qualified Web.ActivityPub as AP
import Database.Persist.Local
import Vervis.Actor import Vervis.Actor
import Vervis.Data.Actor import Vervis.Data.Actor
import Vervis.Data.Collab import Vervis.Data.Collab
@ -159,7 +161,10 @@ actorLinkFedW
:: Either (LocalActorBy Key, Actor) (Instance, RemoteObject, RemoteActor) :: Either (LocalActorBy Key, Actor) (Instance, RemoteObject, RemoteActor)
-> Widget -> Widget
actorLinkFedW (Left (c, a)) = actorLinkW c a actorLinkFedW (Left (c, a)) = actorLinkW c a
actorLinkFedW (Right (inztance, object, actor)) = actorLinkFedW (Right (inztance, object, actor)) = do
maybeID <-
handlerToWidget $ runDB $
getKeyBy $ UniqueRemoteActor $ remoteActorIdent actor
[whamlet| [whamlet|
<a href="#{renderObjURI uActor}"> <a href="#{renderObjURI uActor}">
#{marker $ remoteActorType actor} # #{marker $ remoteActorType actor} #
@ -167,6 +172,11 @@ actorLinkFedW (Right (inztance, object, actor)) =
#{name} @ #{renderAuthority $ instanceHost inztance} #{name} @ #{renderAuthority $ instanceHost inztance}
$nothing $nothing
#{renderAuthority $ instanceHost inztance}#{localUriPath $ remoteObjectIdent object} #{renderAuthority $ instanceHost inztance}#{localUriPath $ remoteObjectIdent object}
$maybe actorID <- maybeID
<a href=@{RemoteActorR actorID}>
$nothing
🐞
|] |]
where where
uActor = ObjURI (instanceHost inztance) (remoteObjectIdent object) uActor = ObjURI (instanceHost inztance) (remoteObjectIdent object)

View file

@ -14,6 +14,8 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
^{loomNavW (Entity loomID loom) actor} ^{loomNavW (Entity loomID loom) actor}
^{followW' $ Left $ loomActor loom}
^{personPermitsForResourceW permits} ^{personPermitsForResourceW permits}
<p> <p>

View file

@ -41,6 +41,9 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<span> <span>
<a href=@{BrowseR}> <a href=@{BrowseR}>
[📚 Browse projects] [📚 Browse projects]
<span>
<a href=@{RemoteActorsR}>
[🌁 Browse remote actors]
<span> <span>
<a href=@{HomeR}> <a href=@{HomeR}>
[📣 Publish an activity] [📣 Publish an activity]

View file

@ -14,4 +14,6 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
^{groupNavW (Entity groupID group) actor} ^{groupNavW (Entity groupID group) actor}
^{followW' $ Left $ groupActor group}
^{personPermitsForResourceW permits} ^{personPermitsForResourceW permits}

View file

@ -1,6 +1,7 @@
$# This file is part of Vervis. $# This file is part of Vervis.
$# $#
$# Written in 2016, 2018, 2019, 2022 by fr33domlover <fr33domlover@riseup.net>. $# Written in 2016, 2018, 2019, 2022, 2024
$# by fr33domlover <fr33domlover@riseup.net>.
$# $#
$# ♡ Copying is an act of love. Please copy, reuse and share. $# ♡ Copying is an act of love. Please copy, reuse and share.
$# $#
@ -14,7 +15,7 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
^{avatarW secure $ emailText $ personEmail person} ^{avatarW secure $ emailText $ personEmail person}
^{followButton} ^{followW' $ Left $ personActor person}
<p>#{actorDesc actor} <p>#{actorDesc actor}

View file

@ -14,4 +14,6 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
^{projectNavW (Entity projectID project) actor} ^{projectNavW (Entity projectID project) actor}
^{followW' $ Left $ projectActor project}
^{personPermitsForResourceW permits} ^{personPermitsForResourceW permits}

View file

@ -0,0 +1,39 @@
$# This file is part of Vervis.
$#
$# Written in 2024 by fr33domlover <fr33domlover@riseup.net>.
$#
$# ♡ Copying is an act of love. Please copy, reuse and share.
$#
$# The author(s) have dedicated all copyright and related and neighboring
$# rights to this software to the public domain worldwide. This software is
$# distributed without any warranty.
$#
$# You should have received a copy of the CC0 Public Domain Dedication along
$# with this software. If not, see
$# <http://creativecommons.org/publicdomain/zero/1.0/>.
<div>
<span>
[[ #
^{actorLinkFedW $ Right linkInfo} #
\ ]] ::
<span>
<a href="#{renderObjURI $ ObjURI h luInbox}">
[📥 Inbox]
<span>
[📤 Outbox]
<span>
$maybe luFollowers <- mluFollowers
<a href="#{renderObjURI $ ObjURI h luFollowers}">
[🐤 Followers]
$nothing
[🐤 Followers]
<span>
[🐔 Following]
<div>
$maybe permits <- maybePermits
^{personPermitsForResourceW permits}
<div>
^{followW' $ Right actorID}

View file

@ -0,0 +1,20 @@
$# This file is part of Vervis.
$#
$# Written in 2024 by fr33domlover <fr33domlover@riseup.net>.
$#
$# ♡ Copying is an act of love. Please copy, reuse and share.
$#
$# The author(s) have dedicated all copyright and related and neighboring
$# rights to this software to the public domain worldwide. This software is
$# distributed without any warranty.
$#
$# You should have received a copy of the CC0 Public Domain Dedication along
$# with this software. If not, see
$# <http://creativecommons.org/publicdomain/zero/1.0/>.
<h2>Remote actors known to this instance
<ul>
$forall (Entity _iid i, Entity _roid ro, Entity _raid ra) <- actors
<li>
^{actorLinkFedW $ Right (i, ro, ra)}

View file

@ -61,7 +61,7 @@ $# ^{personNavW user}
^{personPermitsForResourceW permits} ^{personPermitsForResourceW permits}
^{followButton} ^{followW' $ Left $ repoActor repository}
$if not $ null looms $if not $ null looms
<h2>Enable patch tracking <h2>Enable patch tracking

View file

@ -61,7 +61,7 @@ $# ^{personNavW user}
^{personPermitsForResourceW permits} ^{personPermitsForResourceW permits}
^{followButton} ^{followW' $ Left $ repoActor repository}
$if not $ null looms $if not $ null looms
<h2>Enable patch tracking <h2>Enable patch tracking

View file

@ -14,6 +14,8 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
^{deckNavW (Entity deckID deck) actor} ^{deckNavW (Entity deckID deck) actor}
^{followW' $ Left $ deckActor deck}
^{personPermitsForResourceW permits} ^{personPermitsForResourceW permits}
<p> <p>

View file

@ -140,6 +140,14 @@
/accept-invite/#PermitFulfillsInviteKeyHashid AcceptInviteR POST /accept-invite/#PermitFulfillsInviteKeyHashid AcceptInviteR POST
/remote-actors RemoteActorsR GET
/remote-actors/view/#RemoteActorId RemoteActorR GET
/follow/local/#ActorId FollowLocalR POST
/follow/remote/#RemoteActorId FollowRemoteR POST
/unfollow/local/#ActorId UnfollowLocalR POST
/unfollow/remote/#RemoteActorId UnfollowRemoteR POST
---- Person ------------------------------------------------------------------ ---- Person ------------------------------------------------------------------
/people/#PersonKeyHashid PersonR GET /people/#PersonKeyHashid PersonR GET
@ -154,9 +162,6 @@
/people/#PersonKeyHashid/messages/#LocalMessageKeyHashid PersonMessageR GET /people/#PersonKeyHashid/messages/#LocalMessageKeyHashid PersonMessageR GET
/people/#PersonKeyHashid/follow PersonFollowR POST
/people/#PersonKeyHashid/unfollow PersonUnfollowR POST
/people/#PersonKeyHashid/stamps/#SigKeyKeyHashid PersonStampR GET /people/#PersonKeyHashid/stamps/#SigKeyKeyHashid PersonStampR GET
---- Group ------------------------------------------------------------------ ---- Group ------------------------------------------------------------------