ミュート/ブロックでページングと解除ができるように (#5610)

This commit is contained in:
MeiMei 2019-12-15 03:42:33 +09:00 committed by syuilo
parent 4214a0618e
commit d95242cab0
3 changed files with 157 additions and 14 deletions

View file

@ -1225,6 +1225,8 @@ common/views/components/mute-and-block.vue:
word-mute: "ワードミュート" word-mute: "ワードミュート"
muted-words: "ミュートされたキーワード" muted-words: "ミュートされたキーワード"
muted-words-description: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります" muted-words-description: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります"
unmute-confirm: "このユーザーをミュート解除しますか?"
unblock-confirm: "このユーザーをブロック解除しますか?"
save: "保存" save: "保存"
common/views/components/password-settings.vue: common/views/components/password-settings.vue:

View file

@ -0,0 +1,39 @@
<template>
<div class="muteblockuser">
<div class="avatar-link">
<a :href="user | userPage(null, true)">
<mk-avatar class="avatar" :user="user" :disable-link="true"/>
</a>
</div>
<div class="text">
<div><mk-user-name :user="user"/></div>
<div class="username">@{{ user | acct }}</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import i18n from '../../../../i18n';
export default Vue.extend({
i18n: i18n('common/views/components/mute-and-block.user.vue'),
props: ['user'],
});
</script>
<style lang="stylus" scoped>
.muteblockuser
display flex
padding 16px
> .avatar-link
> a
> .avatar
width 40px
height 40px
> .text
color var(--text)
margin-left 16px
</style>

View file

@ -6,9 +6,13 @@
<header>{{ $t('mute') }}</header> <header>{{ $t('mute') }}</header>
<ui-info v-if="!muteFetching && mute.length == 0">{{ $t('no-muted-users') }}</ui-info> <ui-info v-if="!muteFetching && mute.length == 0">{{ $t('no-muted-users') }}</ui-info>
<div class="users" v-if="mute.length != 0"> <div class="users" v-if="mute.length != 0">
<div v-for="user in mute" :key="user.id"> <div class="user" v-for="user in mute" :key="user.id">
<p><b><mk-user-name :user="user"/></b> @{{ user | acct }}</p> <x-user :user="user"/>
<span @click="unmute(user)">
<fa icon="times"/>
</span>
</div> </div>
<ui-button v-if="this.muteCursor != null" @click="updateMute()">{{ $t('@.load-more') }}</ui-button>
</div> </div>
</section> </section>
@ -16,9 +20,13 @@
<header>{{ $t('block') }}</header> <header>{{ $t('block') }}</header>
<ui-info v-if="!blockFetching && block.length == 0">{{ $t('no-blocked-users') }}</ui-info> <ui-info v-if="!blockFetching && block.length == 0">{{ $t('no-blocked-users') }}</ui-info>
<div class="users" v-if="block.length != 0"> <div class="users" v-if="block.length != 0">
<div v-for="user in block" :key="user.id"> <div class="user" v-for="user in block" :key="user.id">
<p><b><mk-user-name :user="user"/></b> @{{ user | acct }}</p> <x-user :user="user"/>
<span @click="unblock(user)">
<fa icon="times"/>
</span>
</div> </div>
<ui-button v-if="this.blockCursor != null" @click="updateBlock()">{{ $t('@.load-more') }}</ui-button>
</div> </div>
</section> </section>
@ -35,16 +43,25 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import i18n from '../../../../i18n'; import i18n from '../../../../i18n';
import XUser from './mute-and-block.user.vue';
const fetchLimit = 30;
export default Vue.extend({ export default Vue.extend({
i18n: i18n('common/views/components/mute-and-block.vue'), i18n: i18n('common/views/components/mute-and-block.vue'),
components: {
XUser
},
data() { data() {
return { return {
muteFetching: true, muteFetching: true,
blockFetching: true, blockFetching: true,
mute: [], mute: [],
block: [], block: [],
muteCursor: undefined,
blockCursor: undefined,
mutedWords: '' mutedWords: ''
}; };
}, },
@ -59,21 +76,106 @@ export default Vue.extend({
mounted() { mounted() {
this.mutedWords = this._mutedWords.map(words => words.join(' ')).join('\n'); this.mutedWords = this._mutedWords.map(words => words.join(' ')).join('\n');
this.$root.api('mute/list').then(mute => { this.updateMute();
this.mute = mute.map(x => x.mutee); this.updateBlock();
this.muteFetching = false;
});
this.$root.api('blocking/list').then(blocking => {
this.block = blocking.map(x => x.blockee);
this.blockFetching = false;
});
}, },
methods: { methods: {
save() { save() {
this._mutedWords = this.mutedWords.split('\n').map(line => line.split(' ').filter(x => x != '')); this._mutedWords = this.mutedWords.split('\n').map(line => line.split(' ').filter(x => x != ''));
},
unmute(user) {
this.$root.dialog({
type: 'warning',
text: this.$t('unmute-confirm'),
showCancelButton: true
}).then(({ canceled }) => {
if (canceled) return;
this.$root.api('mute/delete', {
userId: user.id
}).then(() => {
this.muteCursor = undefined;
this.updateMute();
});
});
},
unblock(user) {
this.$root.dialog({
type: 'warning',
text: this.$t('unblock-confirm'),
showCancelButton: true
}).then(({ canceled }) => {
if (canceled) return;
this.$root.api('blocking/delete', {
userId: user.id
}).then(() => {
this.updateBlock();
});
});
},
updateMute() {
this.muteFetching = true;
this.$root.api('mute/list', {
limit: fetchLimit + 1,
untilId: this.muteCursor,
}).then((items: Object[]) => {
const past = this.muteCursor ? this.mute : [];
if (items.length === fetchLimit + 1) {
items.pop()
this.muteCursor = items[items.length - 1].id;
} else {
this.muteCursor = undefined;
} }
this.mute = past.concat(items.map(x => x.mutee));
this.muteFetching = false;
});
},
updateBlock() {
this.blockFetching = true;
this.$root.api('blocking/list', {
limit: fetchLimit + 1,
untilId: this.blockCursor,
}).then((items: Object[]) => {
const past = this.blockCursor ? this.block : [];
if (items.length === fetchLimit + 1) {
items.pop()
this.blockCursor = items[items.length - 1].id;
} else {
this.blockCursor = undefined;
}
this.block = past.concat(items.map(x => x.blockee));
this.blockFetching = false;
});
},
} }
}); });
</script> </script>
<style lang="stylus" scoped>
.users
> .user
display flex
align-items center
justify-content flex-end
border-radius 6px
&:hover
background-color var(--primary)
> span
margin-left auto
cursor pointer
padding 16px
> button
margin-top 16px
</style>