summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-06-24 13:08:48 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-06-24 13:08:48 +0900
commitabc082f7c06bdefe2eae9d7493757e770897d151 (patch)
tree85004f3d25e2523ea96902814c9e97c5f207ace7 /src
parent4.10.0 (diff)
downloadsharkey-abc082f7c06bdefe2eae9d7493757e770897d151.tar.gz
sharkey-abc082f7c06bdefe2eae9d7493757e770897d151.tar.bz2
sharkey-abc082f7c06bdefe2eae9d7493757e770897d151.zip
リモートフォローフォームを実装するなど
Diffstat (limited to 'src')
-rw-r--r--src/client/app/common/views/pages/follow.vue215
-rw-r--r--src/client/app/desktop/script.ts4
-rw-r--r--src/client/app/desktop/views/pages/user/user.vue6
-rw-r--r--src/client/app/mobile/script.ts4
-rw-r--r--src/server/activitypub.ts16
5 files changed, 225 insertions, 20 deletions
diff --git a/src/client/app/common/views/pages/follow.vue b/src/client/app/common/views/pages/follow.vue
new file mode 100644
index 0000000000..c8e838be85
--- /dev/null
+++ b/src/client/app/common/views/pages/follow.vue
@@ -0,0 +1,215 @@
+<template>
+<div class="syxhndwprovvuqhmyvveewmbqayniwkv" v-if="!fetching" :data-darkmode="$store.state.device.darkmode">
+ <div class="signed-in-as" v-html="'%i18n:@signed-in-as%'.replace('{}', '<b>' + myName + '</b>')"></div>
+
+ <main>
+ <div class="banner" :style="bannerStyle"></div>
+ <mk-avatar class="avatar" :user="user" :disable-preview="true"/>
+ <div class="body">
+ <router-link :to="user | userPage" class="name">{{ user | userName }}</router-link>
+ <span class="username">@{{ user | acct }}</span>
+ <div class="description">
+ <misskey-flavored-markdown v-if="user.description" :text="user.description" :i="$store.state.i"/>
+ </div>
+ </div>
+ </main>
+
+ <button
+ :class="{ wait: followWait, active: user.isFollowing || user.hasPendingFollowRequestFromYou }"
+ @click="onClick"
+ :disabled="followWait">
+ <template v-if="!followWait">
+ <template v-if="user.hasPendingFollowRequestFromYou">%fa:hourglass-half% %i18n:@request-pending%</template>
+ <template v-else-if="user.isFollowing">%fa:minus% %i18n:@following%</template>
+ <template v-else-if="!user.isFollowing && user.isLocked">%fa:plus% %i18n:@follow-request%</template>
+ <template v-else-if="!user.isFollowing && !user.isLocked">%fa:plus% %i18n:@follow%</template>
+ </template>
+ <template v-else>%fa:spinner .pulse .fw%</template>
+ </button>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import parseAcct from '../../../../../acct/parse';
+import getUserName from '../../../../../renderers/get-user-name';
+import Progress from '../../../common/scripts/loading';
+
+export default Vue.extend({
+ data() {
+ return {
+ fetching: true,
+ user: null,
+ followWait: false
+ };
+ },
+
+ computed: {
+ myName(): string {
+ return Vue.filter('userName')(this.$store.state.i);
+ },
+
+ bannerStyle(): any {
+ if (this.user.bannerUrl == null) return {};
+ return {
+ backgroundColor: this.user.bannerColor && this.user.bannerColor.length == 3 ? `rgb(${ this.user.bannerColor.join(',') })` : null,
+ backgroundImage: `url(${ this.user.bannerUrl })`
+ };
+ }
+ },
+
+ created() {
+ this.fetch();
+ },
+
+ methods: {
+ fetch() {
+ const acct = new URL(location.href).searchParams.get('acct');
+ this.fetching = true;
+ Progress.start();
+ (this as any).api('users/show', parseAcct(acct)).then(user => {
+ this.user = user;
+ this.fetching = false;
+ Progress.done();
+ document.title = getUserName(this.user) + ' | Misskey';
+ });
+ },
+
+ async onClick() {
+ this.followWait = true;
+
+ try {
+ if (this.user.isFollowing) {
+ this.user = await (this as any).api('following/delete', {
+ userId: this.user.id
+ });
+ } else {
+ if (this.user.isLocked && this.user.hasPendingFollowRequestFromYou) {
+ this.user = await (this as any).api('following/requests/cancel', {
+ userId: this.user.id
+ });
+ } else if (this.user.isLocked) {
+ this.user = await (this as any).api('following/create', {
+ userId: this.user.id
+ });
+ } else {
+ this.user = await (this as any).api('following/create', {
+ userId: this.user.id
+ });
+ }
+ }
+ } catch (e) {
+ console.error(e);
+ } finally {
+ this.followWait = false;
+ }
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+@import '~const.styl'
+
+root(isDark)
+ padding 32px
+ max-width 500px
+ margin 0 auto
+ text-align center
+ color isDark ? #9baec8 : #868c8c
+
+ $bg = isDark ? #282C37 : #fff
+
+ @media (max-width 400px)
+ padding 16px
+
+ > .signed-in-as
+ margin-bottom 16px
+ font-size 14px
+ color isDark ? #9baec8 : #9daab3
+
+ > main
+ margin-bottom 16px
+ background $bg
+ border-radius 8px
+ box-shadow 0 4px 12px rgba(#000, 0.1)
+ overflow hidden
+
+ > .banner
+ height 128px
+ background-position center
+ background-size cover
+
+ > .avatar
+ display block
+ margin -50px auto 0 auto
+ width 100px
+ height 100px
+ border-radius 100%
+ border solid 4px $bg
+
+ > .body
+ padding 4px 32px 32px 32px
+
+ @media (max-width 400px)
+ padding 4px 16px 16px 16px
+
+ > .name
+ font-size 20px
+ font-weight bold
+
+ > .username
+ display block
+ opacity 0.7
+
+ > .description
+ margin-top 16px
+
+ > button
+ display block
+ user-select none
+ cursor pointer
+ padding 10px 16px
+ margin 0
+ width 100%
+ min-width 150px
+ font-size 14px
+ font-weight bold
+ color $theme-color
+ background transparent
+ outline none
+ border solid 1px $theme-color
+ border-radius 36px
+
+ &:hover
+ background rgba($theme-color, 0.1)
+
+ &:active
+ background rgba($theme-color, 0.2)
+
+ &.active
+ color $theme-color-foreground
+ background $theme-color
+
+ &:hover
+ background lighten($theme-color, 10%)
+ border-color lighten($theme-color, 10%)
+
+ &:active
+ background darken($theme-color, 10%)
+ border-color darken($theme-color, 10%)
+
+ &.wait
+ cursor wait !important
+ opacity 0.7
+
+ *
+ pointer-events none
+
+.syxhndwprovvuqhmyvveewmbqayniwkv[data-darkmode]
+ root(true)
+
+.syxhndwprovvuqhmyvveewmbqayniwkv:not([data-darkmode])
+ root(false)
+
+</style>
diff --git a/src/client/app/desktop/script.ts b/src/client/app/desktop/script.ts
index beb358c7ee..297100e0e0 100644
--- a/src/client/app/desktop/script.ts
+++ b/src/client/app/desktop/script.ts
@@ -36,6 +36,7 @@ import MkSearch from './views/pages/search.vue';
import MkTag from './views/pages/tag.vue';
import MkReversi from './views/pages/reversi.vue';
import MkShare from './views/pages/share.vue';
+import MkFollow from '../common/views/pages/follow.vue';
/**
* init
@@ -67,7 +68,8 @@ init(async (launch) => {
{ path: '/reversi', component: MkReversi },
{ path: '/reversi/:game', component: MkReversi },
{ path: '/@:user', component: MkUser },
- { path: '/notes/:note', component: MkNote }
+ { path: '/notes/:note', component: MkNote },
+ { path: '/authorize-follow', component: MkFollow }
]
});
diff --git a/src/client/app/desktop/views/pages/user/user.vue b/src/client/app/desktop/views/pages/user/user.vue
index 0337befdbd..fc5c900037 100644
--- a/src/client/app/desktop/views/pages/user/user.vue
+++ b/src/client/app/desktop/views/pages/user/user.vue
@@ -1,6 +1,6 @@
<template>
<mk-ui>
- <div class="zwwan0di1v4356rmdbjmwnn32tptpdp2" v-if="!fetching" :data-darkmode="$store.state.device.darkmode">
+ <div class="xygkxeaeontfaokvqmiblezmhvhostak" v-if="!fetching" :data-darkmode="$store.state.device.darkmode">
<div class="is-suspended" v-if="user.isSuspended">%fa:exclamation-triangle% %i18n:@is-suspended%</div>
<div class="is-remote" v-if="user.host != null">%fa:exclamation-triangle% %i18n:@is-remote%<a :href="user.url || user.uri" target="_blank">%i18n:@view-remote%</a></div>
<main>
@@ -149,10 +149,10 @@ root(isDark)
i
color #ccc
-.zwwan0di1v4356rmdbjmwnn32tptpdp2[data-darkmode]
+.xygkxeaeontfaokvqmiblezmhvhostak[data-darkmode]
root(true)
-.zwwan0di1v4356rmdbjmwnn32tptpdp2:not([data-darkmode])
+.xygkxeaeontfaokvqmiblezmhvhostak:not([data-darkmode])
root(false)
</style>
diff --git a/src/client/app/mobile/script.ts b/src/client/app/mobile/script.ts
index cfa9654e61..cb43f9d520 100644
--- a/src/client/app/mobile/script.ts
+++ b/src/client/app/mobile/script.ts
@@ -38,6 +38,7 @@ import MkSettings from './views/pages/settings.vue';
import MkReversi from './views/pages/reversi.vue';
import MkTag from './views/pages/tag.vue';
import MkShare from './views/pages/share.vue';
+import MkFollow from '../common/views/pages/follow.vue';
/**
* init
@@ -80,7 +81,8 @@ init((launch) => {
{ path: '/@:user', component: MkUser },
{ path: '/@:user/followers', component: MkFollowers },
{ path: '/@:user/following', component: MkFollowing },
- { path: '/notes/:note', component: MkNote }
+ { path: '/notes/:note', component: MkNote },
+ { path: '/authorize-follow', component: MkFollow }
]
});
diff --git a/src/server/activitypub.ts b/src/server/activitypub.ts
index 1fbc621e91..f8a01a6ffe 100644
--- a/src/server/activitypub.ts
+++ b/src/server/activitypub.ts
@@ -11,7 +11,7 @@ import renderNote from '../remote/activitypub/renderer/note';
import renderKey from '../remote/activitypub/renderer/key';
import renderPerson from '../remote/activitypub/renderer/person';
import renderOrderedCollection from '../remote/activitypub/renderer/ordered-collection';
-//import parseAcct from '../acct/parse';
+import parseAcct from '../acct/parse';
import config from '../config';
// Init router
@@ -142,20 +142,6 @@ router.get('/@:user', async (ctx, next) => {
userInfo(ctx, user);
});
-
-// follow form
-router.get('/authorize-follow', async ctx => {
- /* TODO
- const { username, host } = parseAcct(ctx.query.acct);
- if (host === null) {
- res.sendStatus(422);
- return;
- }
-
- const finger = await request(`https://${host}`)
- */
-});
-
//#endregion
export default router;