[Client] Fix #3213

This commit is contained in:
syuilo 2018-11-13 16:19:46 +09:00
parent 4a6722b9e9
commit 7896242f57
No known key found for this signature in database
GPG key ID: BDC4C49D06AB9D69
15 changed files with 196 additions and 320 deletions

View file

@ -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: "フォロー許可待ち"

View 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>

View file

@ -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);

View file

@ -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>

View file

@ -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);

View file

@ -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>

View file

@ -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

View file

@ -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>

View file

@ -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

View file

@ -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>

View file

@ -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

View file

@ -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>

View file

@ -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);

View file

@ -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

View file

@ -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