UI: Remote actor view + follow UI
This commit is contained in:
parent
a428bd74ab
commit
6cdd332d1d
20 changed files with 375 additions and 62 deletions
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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}
|
||||||
|
|
||||||
|
|
|
@ -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}
|
||||||
|
|
39
templates/remote-actor.hamlet
Normal file
39
templates/remote-actor.hamlet
Normal 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}
|
20
templates/remote-actors.hamlet
Normal file
20
templates/remote-actors.hamlet
Normal 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)}
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
11
th/routes
11
th/routes
|
@ -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 ------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in a new issue