[Client] Fix #3213
This commit is contained in:
parent
4a6722b9e9
commit
7896242f57
15 changed files with 196 additions and 320 deletions
|
@ -668,13 +668,6 @@ desktop/views/components/media-video.vue:
|
||||||
sensitive: "閲覧注意"
|
sensitive: "閲覧注意"
|
||||||
click-to-show: "クリックして表示"
|
click-to-show: "クリックして表示"
|
||||||
|
|
||||||
desktop/views/components/follow-button.vue:
|
|
||||||
following: "フォロー中"
|
|
||||||
follow: "フォロー"
|
|
||||||
request-pending: "フォロー許可待ち"
|
|
||||||
follow-processing: "フォロー処理中"
|
|
||||||
follow-request: "フォロー申請"
|
|
||||||
|
|
||||||
desktop/views/components/followers-window.vue:
|
desktop/views/components/followers-window.vue:
|
||||||
followers: "{} のフォロワー"
|
followers: "{} のフォロワー"
|
||||||
|
|
||||||
|
@ -1336,7 +1329,7 @@ mobile/views/components/media-video.vue:
|
||||||
sensitive: "閲覧注意"
|
sensitive: "閲覧注意"
|
||||||
click-to-show: "クリックして表示"
|
click-to-show: "クリックして表示"
|
||||||
|
|
||||||
mobile/views/components/follow-button.vue:
|
common/views/components/follow-button.vue:
|
||||||
following: "フォロー中"
|
following: "フォロー中"
|
||||||
follow: "フォロー"
|
follow: "フォロー"
|
||||||
request-pending: "フォロー許可待ち"
|
request-pending: "フォロー許可待ち"
|
||||||
|
|
184
src/client/app/common/views/components/follow-button.vue
Normal file
184
src/client/app/common/views/components/follow-button.vue
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
<template>
|
||||||
|
<button class="wfliddvnhxvyusikowhxozkyxyenqxqr"
|
||||||
|
:class="{ wait, block, mini, active: isFollowing || hasPendingFollowRequestFromYou }"
|
||||||
|
@click="onClick"
|
||||||
|
:disabled="wait"
|
||||||
|
>
|
||||||
|
<template v-if="!wait">
|
||||||
|
<fa :icon="iconAndText[0]"/> <template v-if="!mini">{{ iconAndText[1] }}</template>
|
||||||
|
</template>
|
||||||
|
<template v-else><fa icon="spinner" pulse fixed-width/></template>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import i18n from '../../../i18n';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n: i18n('common/views/components/follow-button.vue'),
|
||||||
|
|
||||||
|
props: {
|
||||||
|
user: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
block: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
mini: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isFollowing: this.user.isFollowing,
|
||||||
|
hasPendingFollowRequestFromYou: this.user.hasPendingFollowRequestFromYou,
|
||||||
|
wait: false,
|
||||||
|
connection: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
iconAndText(): any[] {
|
||||||
|
return (
|
||||||
|
(this.hasPendingFollowRequestFromYou && this.user.isLocked) ? ['hourglass-half', this.$t('request-pending')] :
|
||||||
|
(this.hasPendingFollowRequestFromYou && !this.user.isLocked) ? ['hourglass-start', this.$t('follow-processing')] :
|
||||||
|
(this.isFollowing) ? ['minus', this.$t('following')] :
|
||||||
|
(!this.isFollowing && this.user.isLocked) ? ['plus', this.$t('follow-request')] :
|
||||||
|
(!this.isFollowing && !this.user.isLocked) ? ['plus', this.$t('follow')] :
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.connection = this.$root.stream.useSharedConnection('main');
|
||||||
|
|
||||||
|
this.connection.on('follow', this.onFollowChange);
|
||||||
|
this.connection.on('unfollow', this.onFollowChange);
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
this.connection.dispose();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onFollowChange(user) {
|
||||||
|
if (user.id == this.user.id) {
|
||||||
|
this.isFollowing = user.isFollowing;
|
||||||
|
this.hasPendingFollowRequestFromYou = user.hasPendingFollowRequestFromYou;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async onClick() {
|
||||||
|
this.wait = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (this.isFollowing) {
|
||||||
|
await this.$root.api('following/delete', {
|
||||||
|
userId: this.user.id
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (this.hasPendingFollowRequestFromYou) {
|
||||||
|
await this.$root.api('following/requests/cancel', {
|
||||||
|
userId: this.user.id
|
||||||
|
});
|
||||||
|
} else if (this.user.isLocked) {
|
||||||
|
await this.$root.api('following/create', {
|
||||||
|
userId: this.user.id
|
||||||
|
});
|
||||||
|
this.hasPendingFollowRequestFromYou = true;
|
||||||
|
} else {
|
||||||
|
await this.$root.api('following/create', {
|
||||||
|
userId: this.user.id
|
||||||
|
});
|
||||||
|
this.hasPendingFollowRequestFromYou = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
} finally {
|
||||||
|
this.wait = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.wfliddvnhxvyusikowhxozkyxyenqxqr
|
||||||
|
display block
|
||||||
|
user-select none
|
||||||
|
cursor pointer
|
||||||
|
padding 0 16px
|
||||||
|
margin 0
|
||||||
|
min-width 100px
|
||||||
|
line-height 36px
|
||||||
|
font-size 14px
|
||||||
|
font-weight bold
|
||||||
|
color var(--primary)
|
||||||
|
background transparent
|
||||||
|
outline none
|
||||||
|
border solid 1px var(--primary)
|
||||||
|
border-radius 36px
|
||||||
|
|
||||||
|
&.mini
|
||||||
|
padding 0
|
||||||
|
min-width 0
|
||||||
|
width 32px
|
||||||
|
height 32px
|
||||||
|
font-size 16px
|
||||||
|
border-radius 4px
|
||||||
|
line-height 32px
|
||||||
|
|
||||||
|
&:focus
|
||||||
|
&:after
|
||||||
|
border-radius 8px
|
||||||
|
|
||||||
|
&.block
|
||||||
|
width 100%
|
||||||
|
|
||||||
|
&:focus
|
||||||
|
&:after
|
||||||
|
content ""
|
||||||
|
pointer-events none
|
||||||
|
position absolute
|
||||||
|
top -5px
|
||||||
|
right -5px
|
||||||
|
bottom -5px
|
||||||
|
left -5px
|
||||||
|
border 2px solid var(--primaryAlpha03)
|
||||||
|
border-radius 36px
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
background var(--primaryAlpha01)
|
||||||
|
|
||||||
|
&:active
|
||||||
|
background var(--primaryAlpha02)
|
||||||
|
|
||||||
|
&.active
|
||||||
|
color var(--primaryForeground)
|
||||||
|
background var(--primary)
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
background var(--primaryLighten10)
|
||||||
|
border-color var(--primaryLighten10)
|
||||||
|
|
||||||
|
&:active
|
||||||
|
background var(--primaryDarken10)
|
||||||
|
border-color var(--primaryDarken10)
|
||||||
|
|
||||||
|
&.wait
|
||||||
|
cursor wait !important
|
||||||
|
opacity 0.7
|
||||||
|
|
||||||
|
*
|
||||||
|
pointer-events none
|
||||||
|
|
||||||
|
</style>
|
|
@ -1,5 +1,6 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
import followButton from './follow-button.vue';
|
||||||
import muteAndBlock from './mute-and-block.vue';
|
import muteAndBlock from './mute-and-block.vue';
|
||||||
import error from './error.vue';
|
import error from './error.vue';
|
||||||
import apiSettings from './api-settings.vue';
|
import apiSettings from './api-settings.vue';
|
||||||
|
@ -51,6 +52,7 @@ import uiInfo from './ui/info.vue';
|
||||||
import formButton from './ui/form/button.vue';
|
import formButton from './ui/form/button.vue';
|
||||||
import formRadio from './ui/form/radio.vue';
|
import formRadio from './ui/form/radio.vue';
|
||||||
|
|
||||||
|
Vue.component('mk-follow-button', followButton);
|
||||||
Vue.component('mk-mute-and-block', muteAndBlock);
|
Vue.component('mk-mute-and-block', muteAndBlock);
|
||||||
Vue.component('mk-error', error);
|
Vue.component('mk-error', error);
|
||||||
Vue.component('mk-api-settings', apiSettings);
|
Vue.component('mk-api-settings', apiSettings);
|
||||||
|
|
|
@ -1,157 +0,0 @@
|
||||||
<template>
|
|
||||||
<button class="mk-follow-button"
|
|
||||||
:class="{ wait, active: u.isFollowing || u.hasPendingFollowRequestFromYou, big: size == 'big' }"
|
|
||||||
@click="onClick"
|
|
||||||
:disabled="wait"
|
|
||||||
>
|
|
||||||
<template v-if="!wait">
|
|
||||||
<template v-if="u.hasPendingFollowRequestFromYou && u.isLocked"><fa icon="hourglass-half"/><template v-if="size == 'big'"> {{ $t('request-pending') }}</template></template>
|
|
||||||
<template v-else-if="u.hasPendingFollowRequestFromYou && !u.isLocked"><fa icon="hourglass-start"/><template v-if="size == 'big'"> {{ $t('follow-processing') }}</template></template>
|
|
||||||
<template v-else-if="u.isFollowing"><fa icon="minus"/><template v-if="size == 'big'"> {{ $t('following') }}</template></template>
|
|
||||||
<template v-else-if="!u.isFollowing && u.isLocked"><fa icon="plus"/><template v-if="size == 'big'"> {{ $t('follow-request') }}</template></template>
|
|
||||||
<template v-else-if="!u.isFollowing && !u.isLocked"><fa icon="plus"/><template v-if="size == 'big'"> {{ $t('follow') }}</template></template>
|
|
||||||
</template>
|
|
||||||
<template v-else><fa icon="spinner .pulse" fixed-width/></template>
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
import i18n from '../../../i18n';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
i18n: i18n('desktop/views/components/follow-button.vue'),
|
|
||||||
props: {
|
|
||||||
user: {
|
|
||||||
type: Object,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
type: String,
|
|
||||||
default: 'compact'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
u: this.user,
|
|
||||||
wait: false,
|
|
||||||
connection: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
this.connection = this.$root.stream.useSharedConnection('main');
|
|
||||||
this.connection.on('follow', this.onFollowChange);
|
|
||||||
this.connection.on('unfollow', this.onFollowChange);
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeDestroy() {
|
|
||||||
this.connection.dispose();
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
onFollowChange(user) {
|
|
||||||
if (user.id == this.u.id) {
|
|
||||||
this.u.isFollowing = user.isFollowing;
|
|
||||||
this.u.hasPendingFollowRequestFromYou = user.hasPendingFollowRequestFromYou;
|
|
||||||
this.$forceUpdate();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async onClick() {
|
|
||||||
this.wait = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (this.u.isFollowing) {
|
|
||||||
this.u = await this.$root.api('following/delete', {
|
|
||||||
userId: this.u.id
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (this.u.hasPendingFollowRequestFromYou) {
|
|
||||||
this.u = await this.$root.api('following/requests/cancel', {
|
|
||||||
userId: this.u.id
|
|
||||||
});
|
|
||||||
} else if (this.u.isLocked) {
|
|
||||||
this.u = await this.$root.api('following/create', {
|
|
||||||
userId: this.u.id
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.u = await this.$root.api('following/create', {
|
|
||||||
userId: this.user.id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
} finally {
|
|
||||||
this.wait = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
|
||||||
.mk-follow-button
|
|
||||||
display block
|
|
||||||
cursor pointer
|
|
||||||
padding 0
|
|
||||||
margin 0
|
|
||||||
width 32px
|
|
||||||
height 32px
|
|
||||||
font-size 1em
|
|
||||||
outline none
|
|
||||||
border-radius 4px
|
|
||||||
|
|
||||||
*
|
|
||||||
pointer-events none
|
|
||||||
|
|
||||||
&:focus
|
|
||||||
&:after
|
|
||||||
content ""
|
|
||||||
pointer-events none
|
|
||||||
position absolute
|
|
||||||
top -5px
|
|
||||||
right -5px
|
|
||||||
bottom -5px
|
|
||||||
left -5px
|
|
||||||
border 2px solid var(--primaryAlpha03)
|
|
||||||
border-radius 8px
|
|
||||||
|
|
||||||
&:not(.active)
|
|
||||||
color var(--primary)
|
|
||||||
border solid 1px var(--primary)
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
background var(--primaryAlpha03)
|
|
||||||
|
|
||||||
&:active
|
|
||||||
background var(--primaryAlpha05)
|
|
||||||
|
|
||||||
&.active
|
|
||||||
color var(--primaryForeground)
|
|
||||||
background var(--primary)
|
|
||||||
border solid 1px var(--primary)
|
|
||||||
|
|
||||||
&:not(:disabled)
|
|
||||||
font-weight bold
|
|
||||||
|
|
||||||
&:hover:not(:disabled)
|
|
||||||
background var(--primaryLighten5)
|
|
||||||
border-color var(--primaryLighten5)
|
|
||||||
|
|
||||||
&:active:not(:disabled)
|
|
||||||
background var(--primaryDarken5)
|
|
||||||
border-color var(--primaryDarken5)
|
|
||||||
|
|
||||||
&.wait
|
|
||||||
cursor wait !important
|
|
||||||
opacity 0.7
|
|
||||||
|
|
||||||
&.big
|
|
||||||
width 100%
|
|
||||||
height 38px
|
|
||||||
line-height 38px
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -14,7 +14,6 @@ import mediaVideo from './media-video.vue';
|
||||||
import notifications from './notifications.vue';
|
import notifications from './notifications.vue';
|
||||||
import noteForm from './post-form.vue';
|
import noteForm from './post-form.vue';
|
||||||
import renoteForm from './renote-form.vue';
|
import renoteForm from './renote-form.vue';
|
||||||
import followButton from './follow-button.vue';
|
|
||||||
import notePreview from './note-preview.vue';
|
import notePreview from './note-preview.vue';
|
||||||
import noteDetail from './note-detail.vue';
|
import noteDetail from './note-detail.vue';
|
||||||
import settings from './settings.vue';
|
import settings from './settings.vue';
|
||||||
|
@ -39,7 +38,6 @@ Vue.component('mk-media-video', mediaVideo);
|
||||||
Vue.component('mk-notifications', notifications);
|
Vue.component('mk-notifications', notifications);
|
||||||
Vue.component('mk-post-form', noteForm);
|
Vue.component('mk-post-form', noteForm);
|
||||||
Vue.component('mk-renote-form', renoteForm);
|
Vue.component('mk-renote-form', renoteForm);
|
||||||
Vue.component('mk-follow-button', followButton);
|
|
||||||
Vue.component('mk-note-preview', notePreview);
|
Vue.component('mk-note-preview', notePreview);
|
||||||
Vue.component('mk-note-detail', noteDetail);
|
Vue.component('mk-note-detail', noteDetail);
|
||||||
Vue.component('mk-settings', settings);
|
Vue.component('mk-settings', settings);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="zvdbznxvfixtmujpsigoccczftvpiwqh">
|
<div class="zvdbznxvfixtmujpsigoccczftvpiwqh">
|
||||||
<div class="banner" :style="bannerStyle"></div>
|
<div class="banner" :style="bannerStyle"></div>
|
||||||
<mk-avatar class="avatar" :user="user" :disable-preview="true"/>
|
<mk-avatar class="avatar" :user="user" :disable-preview="true"/>
|
||||||
<mk-follow-button :user="user" class="follow"/>
|
<mk-follow-button :user="user" class="follow" mini/>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<router-link :to="user | userPage" class="name">{{ user | userName }}</router-link>
|
<router-link :to="user | userPage" class="name">{{ user | userName }}</router-link>
|
||||||
<span class="username">@{{ user | acct }}</span>
|
<span class="username">@{{ user | acct }}</span>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<p>{{ $t('followers') }}</p><span>{{ u.followersCount }}</span>
|
<p>{{ $t('followers') }}</p><span>{{ u.followersCount }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<mk-follow-button v-if="$store.getters.isSignedIn && u.id != $store.state.i.id" :user="u"/>
|
<mk-follow-button class="follow-button" v-if="$store.getters.isSignedIn && u.id != $store.state.i.id" :user="u" mini/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -154,7 +154,7 @@ export default Vue.extend({
|
||||||
font-size 1em
|
font-size 1em
|
||||||
color var(--primary)
|
color var(--primary)
|
||||||
|
|
||||||
> .mk-follow-button
|
> .follow-button
|
||||||
position absolute
|
position absolute
|
||||||
top 92px
|
top 92px
|
||||||
right 8px
|
right 8px
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<header :style="bannerStyle">
|
<header :style="bannerStyle">
|
||||||
<div>
|
<div>
|
||||||
<button class="menu" @click="menu" ref="menu"><fa icon="ellipsis-h"/></button>
|
<button class="menu" @click="menu" ref="menu"><fa icon="ellipsis-h"/></button>
|
||||||
<mk-follow-button v-if="$store.getters.isSignedIn && user.id != $store.state.i.id" :user="user" class="follow"/>
|
<mk-follow-button v-if="$store.getters.isSignedIn && user.id != $store.state.i.id" :user="user" class="follow" mini/>
|
||||||
<mk-avatar class="avatar" :user="user" :disable-preview="true"/>
|
<mk-avatar class="avatar" :user="user" :disable-preview="true"/>
|
||||||
<span class="name">{{ user | userName }}</span>
|
<span class="name">{{ user | userName }}</span>
|
||||||
<span class="acct">@{{ user | acct }}</span>
|
<span class="acct">@{{ user | acct }}</span>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<router-link class="name" :to="friend | userPage" v-user-preview="friend.id">{{ friend.name }}</router-link>
|
<router-link class="name" :to="friend | userPage" v-user-preview="friend.id">{{ friend.name }}</router-link>
|
||||||
<p class="username">@{{ friend | acct }}</p>
|
<p class="username">@{{ friend | acct }}</p>
|
||||||
</div>
|
</div>
|
||||||
<mk-follow-button :user="friend"/>
|
<mk-follow-button class="follow-button" :user="friend"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<p class="empty" v-if="!fetching && users.length == 0">{{ $t('no-users') }}</p>
|
<p class="empty" v-if="!fetching && users.length == 0">{{ $t('no-users') }}</p>
|
||||||
|
@ -110,7 +110,7 @@ export default Vue.extend({
|
||||||
color var(--text)
|
color var(--text)
|
||||||
opacity 0.7
|
opacity 0.7
|
||||||
|
|
||||||
> .mk-follow-button
|
> .follow-button
|
||||||
position absolute
|
position absolute
|
||||||
top 16px
|
top 16px
|
||||||
right 16px
|
right 16px
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="profile" v-if="$store.getters.isSignedIn">
|
<div class="profile" v-if="$store.getters.isSignedIn">
|
||||||
<div class="friend-form" v-if="$store.state.i.id != user.id">
|
<div class="friend-form" v-if="$store.state.i.id != user.id">
|
||||||
<mk-follow-button :user="user" size="big"/>
|
<mk-follow-button :user="user" block/>
|
||||||
<p class="followed" v-if="user.isFollowed">{{ $t('follows-you') }}</p>
|
<p class="followed" v-if="user.isFollowed">{{ $t('follows-you') }}</p>
|
||||||
<p class="stalk" v-if="user.isFollowing">
|
<p class="stalk" v-if="user.isFollowing">
|
||||||
<span v-if="user.isStalking">{{ $t('stalking') }} <a @click="unstalk"><fa icon="meh"/> {{ $t('unstalk') }}</a></span>
|
<span v-if="user.isStalking">{{ $t('stalking') }} <a @click="unstalk"><fa icon="meh"/> {{ $t('unstalk') }}</a></span>
|
||||||
|
|
|
@ -114,11 +114,6 @@ export default define({
|
||||||
color var(--text)
|
color var(--text)
|
||||||
opacity 0.7
|
opacity 0.7
|
||||||
|
|
||||||
> .mk-follow-button
|
|
||||||
position absolute
|
|
||||||
top 16px
|
|
||||||
right 16px
|
|
||||||
|
|
||||||
> .empty
|
> .empty
|
||||||
margin 0
|
margin 0
|
||||||
padding 16px
|
padding 16px
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
<template>
|
|
||||||
<button class="mk-follow-button"
|
|
||||||
:class="{ wait: wait, active: u.isFollowing || u.hasPendingFollowRequestFromYou }"
|
|
||||||
@click="onClick"
|
|
||||||
:disabled="wait"
|
|
||||||
>
|
|
||||||
<template v-if="!wait">
|
|
||||||
<template v-if="u.hasPendingFollowRequestFromYou && u.isLocked"><fa icon="hourglass-half"/> {{ $t('request-pending') }}</template>
|
|
||||||
<template v-else-if="u.hasPendingFollowRequestFromYou && !u.isLocked"><fa icon="hourglass-start"/> {{ $t('follow-processing') }}</template>
|
|
||||||
<template v-else-if="u.isFollowing"><fa icon="minus"/> {{ $t('following') }}</template>
|
|
||||||
<template v-else-if="!u.isFollowing && u.isLocked"><fa icon="plus"/> {{ $t('follow-request') }}</template>
|
|
||||||
<template v-else-if="!u.isFollowing && !u.isLocked"><fa icon="plus"/> {{ $t('follow') }}</template>
|
|
||||||
</template>
|
|
||||||
<template v-else><fa icon="spinner .pulse" fixed-width/></template>
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
import i18n from '../../../i18n';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
i18n: i18n('mobile/views/components/follow-button.vue'),
|
|
||||||
props: {
|
|
||||||
user: {
|
|
||||||
type: Object,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
u: this.user,
|
|
||||||
wait: false,
|
|
||||||
connection: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
this.connection = this.$root.stream.useSharedConnection('main');
|
|
||||||
|
|
||||||
this.connection.on('follow', this.onFollowChange);
|
|
||||||
this.connection.on('unfollow', this.onFollowChange);
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeDestroy() {
|
|
||||||
this.connection.dispose();
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
onFollowChange(user) {
|
|
||||||
if (user.id == this.u.id) {
|
|
||||||
this.u.isFollowing = user.isFollowing;
|
|
||||||
this.u.hasPendingFollowRequestFromYou = user.hasPendingFollowRequestFromYou;
|
|
||||||
this.$forceUpdate();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async onClick() {
|
|
||||||
this.wait = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (this.u.isFollowing) {
|
|
||||||
this.u = await this.$root.api('following/delete', {
|
|
||||||
userId: this.u.id
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (this.u.hasPendingFollowRequestFromYou) {
|
|
||||||
this.u = await this.$root.api('following/requests/cancel', {
|
|
||||||
userId: this.u.id
|
|
||||||
});
|
|
||||||
} else if (this.u.isLocked) {
|
|
||||||
this.u = await this.$root.api('following/create', {
|
|
||||||
userId: this.u.id
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.u = await this.$root.api('following/create', {
|
|
||||||
userId: this.user.id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
} finally {
|
|
||||||
this.wait = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
|
||||||
.mk-follow-button
|
|
||||||
display block
|
|
||||||
user-select none
|
|
||||||
cursor pointer
|
|
||||||
padding 0 16px
|
|
||||||
margin 0
|
|
||||||
min-width 100px
|
|
||||||
line-height 36px
|
|
||||||
font-size 14px
|
|
||||||
font-weight bold
|
|
||||||
color var(--primary)
|
|
||||||
background transparent
|
|
||||||
outline none
|
|
||||||
border solid 1px var(--primary)
|
|
||||||
border-radius 36px
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
background var(--primaryAlpha01)
|
|
||||||
|
|
||||||
&:active
|
|
||||||
background var(--primaryAlpha02)
|
|
||||||
|
|
||||||
&.active
|
|
||||||
color var(--primaryForeground)
|
|
||||||
background var(--primary)
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
background var(--primaryLighten10)
|
|
||||||
border-color var(--primaryLighten10)
|
|
||||||
|
|
||||||
&:active
|
|
||||||
background var(--primaryDarken10)
|
|
||||||
border-color var(--primaryDarken10)
|
|
||||||
|
|
||||||
&.wait
|
|
||||||
cursor wait !important
|
|
||||||
opacity 0.7
|
|
||||||
|
|
||||||
*
|
|
||||||
pointer-events none
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -10,7 +10,6 @@ import subNoteContent from './sub-note-content.vue';
|
||||||
import noteCard from './note-card.vue';
|
import noteCard from './note-card.vue';
|
||||||
import userCard from './user-card.vue';
|
import userCard from './user-card.vue';
|
||||||
import noteDetail from './note-detail.vue';
|
import noteDetail from './note-detail.vue';
|
||||||
import followButton from './follow-button.vue';
|
|
||||||
import friendsMaker from './friends-maker.vue';
|
import friendsMaker from './friends-maker.vue';
|
||||||
import notification from './notification.vue';
|
import notification from './notification.vue';
|
||||||
import notifications from './notifications.vue';
|
import notifications from './notifications.vue';
|
||||||
|
@ -33,7 +32,6 @@ Vue.component('mk-sub-note-content', subNoteContent);
|
||||||
Vue.component('mk-note-card', noteCard);
|
Vue.component('mk-note-card', noteCard);
|
||||||
Vue.component('mk-user-card', userCard);
|
Vue.component('mk-user-card', userCard);
|
||||||
Vue.component('mk-note-detail', noteDetail);
|
Vue.component('mk-note-detail', noteDetail);
|
||||||
Vue.component('mk-follow-button', followButton);
|
|
||||||
Vue.component('mk-friends-maker', friendsMaker);
|
Vue.component('mk-friends-maker', friendsMaker);
|
||||||
Vue.component('mk-notification', notification);
|
Vue.component('mk-notification', notification);
|
||||||
Vue.component('mk-notifications', notifications);
|
Vue.component('mk-notifications', notifications);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</header>
|
</header>
|
||||||
<a class="name" :href="user | userPage" target="_blank">{{ user | userName }}</a>
|
<a class="name" :href="user | userPage" target="_blank">{{ user | userName }}</a>
|
||||||
<p class="username"><mk-acct :user="user"/></p>
|
<p class="username"><mk-acct :user="user"/></p>
|
||||||
<mk-follow-button :user="user"/>
|
<mk-follow-button class="follow-button" :user="user"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ export default Vue.extend({
|
||||||
font-size 15px
|
font-size 15px
|
||||||
color #ccc
|
color #ccc
|
||||||
|
|
||||||
> .mk-follow-button
|
> .follow-button
|
||||||
display inline-block
|
display inline-block
|
||||||
margin 8px 0 16px 0
|
margin 8px 0 16px 0
|
||||||
|
|
||||||
|
|
|
@ -243,9 +243,6 @@ main
|
||||||
font-size 18px
|
font-size 18px
|
||||||
color var(--text)
|
color var(--text)
|
||||||
|
|
||||||
> .mk-follow-button
|
|
||||||
margin 0
|
|
||||||
|
|
||||||
> .title
|
> .title
|
||||||
margin 8px 0
|
margin 8px 0
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue