webapp: Improved UI for pairing your own devices together using XMPP.

This commit is contained in:
Joey Hess 2013-03-15 15:05:02 -04:00
parent 48d9a3182f
commit 39e979fb65
13 changed files with 145 additions and 72 deletions

View file

@ -274,7 +274,8 @@ pairMsgReceived urlrenderer PairReq theiruuid selfjid theirjid
finishXMPPPairing theirjid theiruuid finishXMPPPairing theirjid theiruuid
-- Show an alert to let the user decide if they want to pair. -- Show an alert to let the user decide if they want to pair.
showalert = do showalert = do
let route = ConfirmXMPPPairR (PairKey theiruuid $ formatJID theirjid) let route = ConfirmXMPPPairFriendR $
PairKey theiruuid $ formatJID theirjid
url <- liftIO $ renderUrl urlrenderer route [] url <- liftIO $ renderUrl urlrenderer route []
close <- asIO1 removeAlert close <- asIO1 removeAlert
void $ addAlert $ pairRequestReceivedAlert (T.unpack $ buddyName theirjid) void $ addAlert $ pairRequestReceivedAlert (T.unpack $ buddyName theirjid)

View file

@ -25,7 +25,6 @@ import Utility.Network
import Annex.UUID import Annex.UUID
#endif #endif
#ifdef WITH_XMPP #ifdef WITH_XMPP
import Assistant.XMPP
import Assistant.XMPP.Client import Assistant.XMPP.Client
import Assistant.XMPP.Buddies import Assistant.XMPP.Buddies
import Assistant.XMPP.Git import Assistant.XMPP.Git
@ -50,45 +49,78 @@ import Control.Concurrent
import qualified Data.Set as S import qualified Data.Set as S
#endif #endif
getStartXMPPPairR :: Handler RepHtml getStartXMPPPairFriendR :: Handler RepHtml
#ifdef WITH_XMPP #ifdef WITH_XMPP
getStartXMPPPairR = ifM (isJust <$> liftAnnex getXMPPCreds) getStartXMPPPairFriendR = ifM (isJust <$> liftAnnex getXMPPCreds)
( do ( do
{- Ask buddies to send presence info, to get {- Ask buddies to send presence info, to get
- the buddy list populated. -} - the buddy list populated. -}
liftAssistant $ sendNetMessage QueryPresence liftAssistant $ sendNetMessage QueryPresence
pairPage $ pairPage $
$(widgetFile "configurators/pairing/xmpp/prompt") $(widgetFile "configurators/pairing/xmpp/friend/prompt")
, redirect XMPPR -- go get XMPP configured, then come back , redirect XMPPR -- go get XMPP configured, then come back
) )
#else #else
getStartXMPPPairR = noXMPPPairing getStartXMPPPairFriendR = noXMPPPairing
noXMPPPairing :: Handler RepHtml noXMPPPairing :: Handler RepHtml
noXMPPPairing = noPairing "XMPP" noXMPPPairing = noPairing "XMPP"
#endif #endif
{- Does pairing with an XMPP buddy, or with other clients sharing an getStartXMPPPairSelfR :: Handler RepHtml
- XMPP account. -}
getRunningXMPPPairR :: BuddyKey -> Handler RepHtml
#ifdef WITH_XMPP #ifdef WITH_XMPP
getRunningXMPPPairR bid = do getStartXMPPPairSelfR = go =<< liftAnnex getXMPPCreds
where
go Nothing = redirect XMPPR -- go get XMPP configured, then come back
go (Just creds) = do
{- Ask buddies to send presence info, to get
- the buddy list populated. -}
liftAssistant $ sendNetMessage QueryPresence
let account = xmppJID creds
pairPage $
$(widgetFile "configurators/pairing/xmpp/self/prompt")
#else
getStartXMPPPairSelfR = noXMPPPairing
noXMPPPairing :: Handler RepHtml
noXMPPPairing = noPairing "XMPP"
#endif
getRunningXMPPPairFriendR :: BuddyKey -> Handler RepHtml
getRunningXMPPPairFriendR = sendXMPPPairRequest . Just
getRunningXMPPPairSelfR :: Handler RepHtml
getRunningXMPPPairSelfR = sendXMPPPairRequest Nothing
{- Sends a XMPP pair request, to a buddy or to self. -}
sendXMPPPairRequest :: Maybe BuddyKey -> Handler RepHtml
#ifdef WITH_XMPP
sendXMPPPairRequest mbid = do
bid <- maybe getself return mbid
buddy <- liftAssistant $ getBuddy bid <<~ buddyList buddy <- liftAssistant $ getBuddy bid <<~ buddyList
go $ S.toList . buddyAssistants <$> buddy go $ S.toList . buddyAssistants <$> buddy
where where
go (Just (clients@((Client exemplar):_))) = do go (Just (clients@((Client exemplar):_))) = do
creds <- liftAnnex getXMPPCreds
let ourjid = fromJust $ parseJID =<< xmppJID <$> creds
let samejid = baseJID ourjid == baseJID exemplar
u <- liftAnnex getUUID u <- liftAnnex getUUID
liftAssistant $ forM_ clients $ \(Client c) -> sendNetMessage $ liftAssistant $ forM_ clients $ \(Client c) -> sendNetMessage $
PairingNotification PairReq (formatJID c) u PairingNotification PairReq (formatJID c) u
xmppPairEnd True $ if samejid then Nothing else Just exemplar xmppPairStatus True $
-- A buddy could have logged out, or the XMPP client restarted, if selfpair then Nothing else Just exemplar
-- and there be no clients to message; handle unforseen by going back. go _
go _ = redirect StartXMPPPairR {- Nudge the user to turn on their other device. -}
| selfpair = do
liftAssistant $ sendNetMessage QueryPresence
pairPage $
$(widgetFile "configurators/pairing/xmpp/self/retry")
{- Buddy could have logged out, etc.
- Go back to buddy list. -}
| otherwise = redirect StartXMPPPairFriendR
selfpair = isNothing mbid
getself = maybe (error "XMPP not configured")
(return . BuddyKey . xmppJID)
=<< liftAnnex getXMPPCreds
#else #else
getRunningXMPPPairR _ = noXMPPPairing sendXMPPPairRequest _ = noXMPPPairing
#endif #endif
{- Starts local pairing. -} {- Starts local pairing. -}
@ -122,20 +154,20 @@ getFinishLocalPairR msg = promptSecret (Just msg) $ \_ secret -> do
getFinishLocalPairR _ = noLocalPairing getFinishLocalPairR _ = noLocalPairing
#endif #endif
getConfirmXMPPPairR :: PairKey -> Handler RepHtml getConfirmXMPPPairFriendR :: PairKey -> Handler RepHtml
#ifdef WITH_XMPP #ifdef WITH_XMPP
getConfirmXMPPPairR pairkey@(PairKey _ t) = case parseJID t of getConfirmXMPPPairFriendR pairkey@(PairKey _ t) = case parseJID t of
Nothing -> error "bad JID" Nothing -> error "bad JID"
Just theirjid -> pairPage $ do Just theirjid -> pairPage $ do
let name = buddyName theirjid let name = buddyName theirjid
$(widgetFile "configurators/pairing/xmpp/confirm") $(widgetFile "configurators/pairing/xmpp/friend/confirm")
#else #else
getConfirmXMPPPairR _ = noXMPPPairing getConfirmXMPPPairFriendR _ = noXMPPPairing
#endif #endif
getFinishXMPPPairR :: PairKey -> Handler RepHtml getFinishXMPPPairFriendR :: PairKey -> Handler RepHtml
#ifdef WITH_XMPP #ifdef WITH_XMPP
getFinishXMPPPairR (PairKey theiruuid t) = case parseJID t of getFinishXMPPPairFriendR (PairKey theiruuid t) = case parseJID t of
Nothing -> error "bad JID" Nothing -> error "bad JID"
Just theirjid -> do Just theirjid -> do
selfuuid <- liftAnnex getUUID selfuuid <- liftAnnex getUUID
@ -143,14 +175,16 @@ getFinishXMPPPairR (PairKey theiruuid t) = case parseJID t of
sendNetMessage $ sendNetMessage $
PairingNotification PairAck (formatJID theirjid) selfuuid PairingNotification PairAck (formatJID theirjid) selfuuid
finishXMPPPairing theirjid theiruuid finishXMPPPairing theirjid theiruuid
xmppPairEnd False $ Just theirjid xmppPairStatus False $ Just theirjid
#else #else
getFinishXMPPPairR _ = noXMPPPairing getFinishXMPPPairR _ = noXMPPPairing
#endif #endif
{- Displays a page indicating pairing status and
- prompting to set up cloud repositories. -}
#ifdef WITH_XMPP #ifdef WITH_XMPP
xmppPairEnd :: Bool -> Maybe JID -> Handler RepHtml xmppPairStatus :: Bool -> Maybe JID -> Handler RepHtml
xmppPairEnd inprogress theirjid = pairPage $ do xmppPairStatus inprogress theirjid = pairPage $ do
let friend = buddyName <$> theirjid let friend = buddyName <$> theirjid
let cloudrepolist = repoListDisplay $ RepoSelector let cloudrepolist = repoListDisplay $ RepoSelector
{ onlyCloud = True { onlyCloud = True

View file

@ -62,7 +62,7 @@ getXMPPR = xmppPage $ do
storecreds creds = do storecreds creds = do
void $ liftAnnex $ setXMPPCreds creds void $ liftAnnex $ setXMPPCreds creds
liftAssistant notifyNetMessagerRestart liftAssistant notifyNetMessagerRestart
redirect StartXMPPPairR redirectBack
#else #else
getXMPPR = xmppPage $ getXMPPR = xmppPage $
$(widgetFile "configurators/xmpp/disabled") $(widgetFile "configurators/xmpp/disabled")
@ -84,6 +84,7 @@ buddyListDisplay = do
autoUpdate ident NotifierBuddyListR (10 :: Int) (10 :: Int) autoUpdate ident NotifierBuddyListR (10 :: Int) (10 :: Int)
#ifdef WITH_XMPP #ifdef WITH_XMPP
myjid <- lift $ liftAssistant $ xmppClientID <$> getDaemonStatus myjid <- lift $ liftAssistant $ xmppClientID <$> getDaemonStatus
let isself (BuddyKey b) = Just b == myjid
buddies <- lift $ liftAssistant $ do buddies <- lift $ liftAssistant $ do
rs <- filter isXMPPRemote . syncGitRemotes <$> getDaemonStatus rs <- filter isXMPPRemote . syncGitRemotes <$> getDaemonStatus
let pairedwith = catMaybes $ map (parseJID . getXMPPClientID) rs let pairedwith = catMaybes $ map (parseJID . getXMPPClientID) rs

View file

@ -42,10 +42,14 @@
/config/repository/pair/local/start StartLocalPairR GET /config/repository/pair/local/start StartLocalPairR GET
/config/repository/pair/local/running/#SecretReminder RunningLocalPairR GET /config/repository/pair/local/running/#SecretReminder RunningLocalPairR GET
/config/repository/pair/local/finish/#PairMsg FinishLocalPairR GET /config/repository/pair/local/finish/#PairMsg FinishLocalPairR GET
/config/repository/pair/xmpp/start StartXMPPPairR GET
/config/repository/pair/xmpp/running/#BuddyKey RunningXMPPPairR GET /config/repository/pair/xmpp/self/start StartXMPPPairSelfR GET
/config/repository/pair/xmpp/accept/#PairKey ConfirmXMPPPairR GET /config/repository/pair/xmpp/self/running RunningXMPPPairSelfR GET
/config/repository/pair/xmpp/finish/#PairKey FinishXMPPPairR GET
/config/repository/pair/xmpp/friend/start StartXMPPPairFriendR GET
/config/repository/pair/xmpp/friend/running/#BuddyKey RunningXMPPPairFriendR GET
/config/repository/pair/xmpp/friend/accept/#PairKey ConfirmXMPPPairFriendR GET
/config/repository/pair/xmpp/friend/finish/#PairKey FinishXMPPPairFriendR GET
/config/repository/enable/rsync/#UUID EnableRsyncR GET /config/repository/enable/rsync/#UUID EnableRsyncR GET
/config/repository/enable/directory/#UUID EnableDirectoryR GET /config/repository/enable/directory/#UUID EnableDirectoryR GET

1
debian/changelog vendored
View file

@ -2,6 +2,7 @@ git-annex (4.20130315) UNRELEASED; urgency=low
* webapp: Repository list is now included in the dashboard, and other * webapp: Repository list is now included in the dashboard, and other
UI tweaks. UI tweaks.
* webapp: Improved UI for pairing your own devices together using XMPP.
-- Joey Hess <joeyh@debian.org> Fri, 15 Mar 2013 00:10:07 -0400 -- Joey Hess <joeyh@debian.org> Fri, 15 Mar 2013 00:10:07 -0400

View file

@ -2,36 +2,33 @@
<a href="@{AddDriveR}"> <a href="@{AddDriveR}">
<i .icon-plus-sign></i> Removable drive <i .icon-plus-sign></i> Removable drive
<p> <p>
Clone this repository to a USB drive, memory stick, or other # Add a USB drive, memory stick, or other removable media. #
removable media.
<p>
For offline archiving, backups, or to # For offline archiving, backups, or to #
<a href="http://en.wikipedia.org/wiki/Sneakernet">SneakerNet</a> # <a href="http://en.wikipedia.org/wiki/Sneakernet">SneakerNet</a> #
between computers. between computers.
<h3>
<a href="@{StartXMPPPairSelfR}">
<i .icon-plus-sign></i> Share with your other devices
<p>
Keep files in sync between your devices running git-annex.
<h3>
<a href="@{StartXMPPPairFriendR}">
<i .icon-plus-sign></i> Share with a friend
<p>
Combine your repository with a friend's repository, and share your files.
<h3> <h3>
<a href="@{StartLocalPairR}"> <a href="@{StartLocalPairR}">
<i .icon-plus-sign></i> Local computer <i .icon-plus-sign></i> Local computer
<p> <p>
Pair with a computer to automatically keep files in sync # Pair with a computer to keep files in sync quickly, #
over your local network. over your local network.
<p>
For easy sharing with friends and devices in the same location.
<h3>
<a href="@{StartXMPPPairR}">
<i .icon-plus-sign></i> Share with a friend
<p>
Pair with a friend's computer, to combine your repositories and #
share files.
<p>
For easy sharing with friends and devices, over the internet.
<h3> <h3>
<a href="@{NewRepositoryR}"> <a href="@{NewRepositoryR}">
<i .icon-plus-sign></i> Add a local repository <i .icon-plus-sign></i> Add another repository
<p> <p>
Make another repository on your computer. Make another repository on your computer.

View file

@ -9,8 +9,7 @@
$nothing $nothing
A pair request has been sent to all other devices that # A pair request has been sent to all other devices that #
have been configured to use your jabber account. # have been configured to use your jabber account. #
It will be answered automatically by any that see it; # It will be answered automatically by any devices that see it.
no action is required on your part.
$else $else
Pair request accepted. Pair request accepted.
<h2> <h2>

View file

@ -5,7 +5,7 @@
Pairing with #{name} will combine your two git annex # Pairing with #{name} will combine your two git annex #
repositories into one, allowing you to share files. repositories into one, allowing you to share files.
<p> <p>
<a .btn .btn-primary .btn-large href="@{FinishXMPPPairR pairkey}"> <a .btn .btn-primary .btn-large href="@{FinishXMPPPairFriendR pairkey}">
Accept pair request Accept pair request
<a .btn .btn-large href="@{DashboardR}"> <a .btn .btn-large href="@{DashboardR}">
No thanks No thanks

View file

@ -0,0 +1,12 @@
<div .span9 .hero-unit>
<h2>
Share with a friend
<p>
You can combine your repository with a friend's repository #
to share your files. Your repositories will automatically be kept in #
sync. Only do this if you want your friend to see all the files #
in this repository!
<p>
Here are the friends currently available via your Jabber account.
<p>
^{buddyListDisplay}

View file

@ -1,11 +0,0 @@
<div .span9 .hero-unit>
<h2>
Pairing with another computer
<p>
Pairing with a another computer combines both git-annex repositories #
into a single shared repository, with changes kept in sync.
<p>
You can pair with any of your friends using jabber, or with another #
device that shares your own jabber account.
<p>
^{buddyListDisplay}

View file

@ -0,0 +1,18 @@
<div .span9 .hero-unit>
<h2>
Sharing with your other devices
<p>
If you have multiple devices, all running git-annex, and using #
your Jabber account #{account}, you can configure them to share #
your files between themselves.
<p>
For example, you can have a computer at home, one at work, and a #
laptop, and their repositories will automatically be kept in sync.
<p>
Make sure your other devices are online and configured to use #
your Jabber account before continuing.
<p>
<a .btn .btn-primary .btn-large href="@{RunningXMPPPairSelfR}">
Start sharing with my other devices #
<a .btn .btn-large href="@{DashboardR}">
Cancel

View file

@ -0,0 +1,11 @@
<div .span9 .hero-unit>
<h2>
Unable to get in touch with any other devices.
<p>
Make sure your other devices are online and configured to use #
your Jabber account before continuing.
<p>
<a .btn .btn-primary .btn-large href="@{RunningXMPPPairSelfR}">
Start sharing with my other devices #
<a .btn .btn-large href="@{DashboardR}">
Cancel

View file

@ -7,16 +7,18 @@
$if isNothing myjid $if isNothing myjid
Not connected to the jabber server. Check your network connection ... Not connected to the jabber server. Check your network connection ...
$else $else
Nobody is currently available. Searching...
$else $else
$forall (name, away, canpair, paired, buddyid) <- buddies $forall (name, away, canpair, paired, buddyid) <- buddies
<tr> <tr>
<td> <td>
<i .icon-user></i> # $if isself buddyid
$if away <i .icon-star></i> #
<span .muted> <span :away:.muted>
#{name} your other devices
$else $else
<i .icon-user></i> #
<span :away:.muted>
#{name} #{name}
<td> <td>
$if away $if away
@ -28,7 +30,11 @@
paired paired
$else $else
$if canpair $if canpair
<a .btn .btn-primary .btn-small href="@{RunningXMPPPairR buddyid}"> $if isself buddyid
<a .btn .btn-primary .btn-small href="@{RunningXMPPPairSelfR}">
Share pairing
$else
<a .btn .btn-primary .btn-small href="@{RunningXMPPPairFriendR buddyid}">
Start pairing Start pairing
$else $else
not using git-annex not using git-annex