diff options
-rw-r--r-- | appinfo/routes.php | 1 | ||||
-rw-r--r-- | lib/Controller/OStatusController.php | 55 | ||||
-rw-r--r-- | src/components/ProfileInfo.vue | 7 | ||||
-rw-r--r-- | src/views/OStatus.vue | 77 |
4 files changed, 113 insertions, 27 deletions
diff --git a/appinfo/routes.php b/appinfo/routes.php index fad134fd..2b64e712 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -55,6 +55,7 @@ return [ ['name' => 'ActivityPub#following', 'url' => '/@{username}/following', 'verb' => 'GET'], ['name' => 'OStatus#subscribe', 'url' => '/ostatus/follow/{uri}', 'verb' => 'GET'], + ['name' => 'OStatus#followRemote', 'url' => '/api/v1/ostatus/followRemote/{local}', 'verb' => 'GET'], ['name' => 'OStatus#getLink', 'url' => '/api/v1/ostatus/link/{local}/{account}', 'verb' => 'GET'], ['name' => 'SocialPub#displayPost', 'url' => '/@{username}/{postId}', 'verb' => 'GET'], diff --git a/lib/Controller/OStatusController.php b/lib/Controller/OStatusController.php index 31eda483..182c4a3d 100644 --- a/lib/Controller/OStatusController.php +++ b/lib/Controller/OStatusController.php @@ -107,7 +107,20 @@ class OStatusController extends Controller { try { $actor = $this->cacheActorService->getFromAccount($uri); - return $this->success([$actor]); + $user = $this->userSession->getUser(); + if ($user === null) { + return $this->fail('Failed to retrieve current user'); + } + + return new TemplateResponse('social', 'ostatus', [ + 'serverData' => [ + 'account' => $actor->getAccount(), + 'currentUser' => [ + 'uid' => $user->getUID(), + 'displayName' => $user->getDisplayName(), + ] + ] + ], 'guest'); } catch (Exception $e) { return $this->fail($e); } @@ -117,6 +130,30 @@ class OStatusController extends Controller { /** * @NoCSRFRequired * @NoAdminRequired + * @PublicPage + * + * @param string $local + * @return Response + */ + public function followRemote(string $local): Response { + try { + $following = $this->accountService->getActor($local); + + return new TemplateResponse('social', 'ostatus', [ + 'serverData' => [ + 'local' => $local, + 'account' => $following->getAccount() + ] + ], 'guest'); + } catch (\Exception $e) { + return $this->fail($e); + } + } + + /** + * @NoCSRFRequired + * @NoAdminRequired + * @PublicPage * * @param string $local * @param string $account @@ -138,24 +175,10 @@ class OStatusController extends Controller { throw new RetrieveAccountFormatException(); } - $user = $this->userSession->getUser(); - if ($user === null) { - return $this->fail('Failed to retrieve current user'); - } - $template = $this->get('template', $link, ''); $url = str_replace('{uri}', $following->getAccount(), $template); - return new TemplateResponse('social', 'ostatus', [ - 'serverData' => [ - 'url' => $url, - 'account' => $account, - 'currentUser' => [ - 'uid' => $user->getUID(), - 'displayName' => $user->getDisplayName(), - ] - ] - ], 'guest'); + return $this->success(['url' => $url]); } catch (Exception $e) { return $this->fail($e); } diff --git a/src/components/ProfileInfo.vue b/src/components/ProfileInfo.vue index 439da6df..e1352084 100644 --- a/src/components/ProfileInfo.vue +++ b/src/components/ProfileInfo.vue @@ -35,6 +35,9 @@ </a> </p> <follow-button :account="accountInfo.account" /> + <button v-if="serverData.public" class="primary" @click="followRemote"> + {{ t('social', 'Follow') }} + </button> </div> <!-- TODO: we have no details, timeline and follower list for non-local accounts for now --> <ul v-if="accountInfo.details && accountInfo.local" class="user-profile--sections"> @@ -145,7 +148,9 @@ export default { } }, methods: { - + followRemote() { + window.open(OC.generateUrl('/apps/social/api/v1/ostatus/followRemote/' + encodeURI(this.uid)), 'followRemote', 'width=433,height=600toolbar=no,menubar=no,scrollbars=yes,resizable=yes') + } } } diff --git a/src/views/OStatus.vue b/src/views/OStatus.vue index dcda26b1..0952d2f8 100644 --- a/src/views/OStatus.vue +++ b/src/views/OStatus.vue @@ -1,33 +1,67 @@ <template> - <div> - <h2>{{ t('social', 'Follow on Nextcloud Social') }}</h2> - <div v-if="accountInfo"> + <div v-if="accountInfo"> + <div v-if="!serverData.local"> + <h2>{{ t('social', 'Follow on Nextcloud Social') }}</h2> <p>{{ t('social', 'Hello') }} <avatar :user="currentUser.uid" :size="16" />{{ currentUser.displayName }}</p> - <p>{{ t('social', 'Please confirm that you want to follow this account:') }}</p> + <p v-if="!isFollowing"> + {{ t('social', 'Please confirm that you want to follow this account:') }} + </p> <avatar :url="avatarUrl" :disable-tooltip="true" :size="128" /> <h2>{{ displayName }}</h2> - <form @submit.prevent="follow"> - <input type="text" :value="serverData.account"> + <form v-if="!isFollowing" @submit.prevent="follow"> <input type="submit" class="primary" value="Follow"> </form> + <p v-else> + <span class="icon icon-checkmark-white" /> + {{ t('social', 'You are following this account') }} + </p> + + <div v-if="isFollowing"> + <button @click="close"> + {{ t('social', 'Close') }} + </button> + </div> + </div> + <div v-if="serverData.local"> + <p>{{ t('social', 'You are going to follow:') }}</p> + <avatar :user="serverData.local" :disable-tooltip="true" :size="128" /> + <h2>{{ displayName }}</h2> + <form @submit.prevent="followRemote"> + <input v-model="remote" type="text" :placeholder="t('social', 'name@domain of your federation account')"> + <input type="submit" class="primary" :value="t('social', 'Continue')"> + </form> + <p>{{ t('social', 'This step is needed as the user is probably not registered on the same server as you are. We will redirect you to your homeserver to follow this account.') }}</p> </div> - <div :class="{ 'icon-loading-dark': !accountInfo }" /> </div> + <div v-else :class="{ 'icon-loading-dark': !accountInfo }" /> </template> <style scoped> h2, p { color: var(--color-primary-text); } + p .icon { + display: inline-block; + } .avatardiv { vertical-align: -4px; margin-right: 3px; + filter: drop-shadow(0 0 0.5rem #333); + margin-top: 10px; + margin-bottom: 20px; + } +</style> + +<style> + .wrapper { + margin-top: 20px; } </style> <script> import { Avatar } from 'nextcloud-vue' +import axios from 'nextcloud-axios' import currentuserMixin from './../mixins/currentUserMixin' export default { @@ -36,7 +70,15 @@ export default { Avatar }, mixins: [currentuserMixin], + data() { + return { + remote: '' + } + }, computed: { + isFollowing() { + return this.$store.getters.isFollowingUser(this.account) + }, account() { return this.serverData.account }, @@ -61,17 +103,32 @@ export default { const serverDataElmt = document.getElementById('serverData') if (serverDataElmt !== null) { const serverData = JSON.parse(document.getElementById('serverData').dataset.server) - window.oc_current_user = JSON.parse(JSON.stringify(serverData.currentUser)) + if (serverData.currentUser) { + window.oc_current_user = JSON.parse(JSON.stringify(serverData.currentUser)) + } this.$store.commit('setServerData', serverData) - this.$store.dispatch('fetchAccountInfo', this.serverData.account) + if (this.serverData.account && !this.serverData.local) { + this.$store.dispatch('fetchAccountInfo', this.serverData.account) + } + if (this.serverData.local) { + this.$store.dispatch('fetchPublicAccountInfo', this.serverData.local) + } } }, methods: { follow() { this.$store.dispatch('followAccount', { currentAccount: this.cloudId, accountToFollow: this.account }).then(() => { - window.location = this.serverData.url + + }) + }, + followRemote() { + axios.get(OC.generateUrl(`/apps/social/api/v1/ostatus/link/${this.serverData.local}/` + encodeURI(this.remote))).then((a) => { + window.location = a.data.result.url }) + }, + close() { + window.close() } } } |