Merge pull request 'feat: Blocking someone should mute them, and disable the ability to mute/unmute them' (#9581) from Feinzer/calckey:issue/9509 into develop
Reviewed-on: https://codeberg.org/calckey/calckey/pulls/9581
This commit is contained in:
commit
c2fe849e14
6 changed files with 59 additions and 12 deletions
|
@ -1,12 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
class="kpoogebi _button"
|
class="kpoogebi _button"
|
||||||
:class="{ wait, active: isFollowing || hasPendingFollowRequestFromYou, full, large }"
|
:class="{
|
||||||
|
wait,
|
||||||
|
active: isFollowing || hasPendingFollowRequestFromYou,
|
||||||
|
full,
|
||||||
|
large,
|
||||||
|
blocking: isBlocking
|
||||||
|
}"
|
||||||
:disabled="wait"
|
:disabled="wait"
|
||||||
@click="onClick"
|
@click="onClick"
|
||||||
>
|
>
|
||||||
<template v-if="!wait">
|
<template v-if="!wait">
|
||||||
<template v-if="hasPendingFollowRequestFromYou && user.isLocked">
|
<template v-if="isBlocking">
|
||||||
|
<span v-if="full">{{ i18n.ts.blocked }}</span><i class="ph-prohibit-bold ph-lg"></i>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="hasPendingFollowRequestFromYou && user.isLocked">
|
||||||
<span v-if="full">{{ i18n.ts.followRequestPending }}</span><i class="ph-hourglass-medium-bold ph-lg"></i>
|
<span v-if="full">{{ i18n.ts.followRequestPending }}</span><i class="ph-hourglass-medium-bold ph-lg"></i>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="hasPendingFollowRequestFromYou && !user.isLocked">
|
<template v-else-if="hasPendingFollowRequestFromYou && !user.isLocked">
|
||||||
|
@ -30,12 +39,13 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onBeforeUnmount, onMounted } from 'vue';
|
import { computed, onBeforeUnmount, onMounted } from 'vue';
|
||||||
import type * as Misskey from 'calckey-js';
|
import type * as Misskey from 'calckey-js';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { stream } from '@/stream';
|
import { stream } from '@/stream';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
user: Misskey.entities.UserDetailed,
|
user: Misskey.entities.UserDetailed,
|
||||||
full?: boolean,
|
full?: boolean,
|
||||||
|
@ -45,6 +55,8 @@ const props = withDefaults(defineProps<{
|
||||||
large: false,
|
large: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const isBlocking = computed(() => props.user.isBlocking);
|
||||||
|
|
||||||
let isFollowing = $ref(props.user.isFollowing);
|
let isFollowing = $ref(props.user.isFollowing);
|
||||||
let hasPendingFollowRequestFromYou = $ref(props.user.hasPendingFollowRequestFromYou);
|
let hasPendingFollowRequestFromYou = $ref(props.user.hasPendingFollowRequestFromYou);
|
||||||
let wait = $ref(false);
|
let wait = $ref(false);
|
||||||
|
@ -68,7 +80,24 @@ async function onClick() {
|
||||||
wait = true;
|
wait = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isFollowing) {
|
if (isBlocking.value) {
|
||||||
|
const { canceled } = await os.confirm({
|
||||||
|
type: 'warning',
|
||||||
|
text: i18n.t('unblockConfirm'),
|
||||||
|
});
|
||||||
|
if (canceled) return
|
||||||
|
|
||||||
|
await os.api("blocking/delete", {
|
||||||
|
userId: props.user.id,
|
||||||
|
})
|
||||||
|
if (props.user.isMuted) {
|
||||||
|
await os.api("mute/delete", {
|
||||||
|
userId: props.user.id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
emit('refresh')
|
||||||
|
}
|
||||||
|
else if (isFollowing) {
|
||||||
const { canceled } = await os.confirm({
|
const { canceled } = await os.confirm({
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
text: i18n.t('unfollowConfirm', { name: props.user.name || props.user.username }),
|
text: i18n.t('unfollowConfirm', { name: props.user.name || props.user.username }),
|
||||||
|
@ -184,4 +213,9 @@ onBeforeUnmount(() => {
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blocking {
|
||||||
|
background-color: var(--bg) !important;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<span>{{ item.text }}</span>
|
<span>{{ item.text }}</span>
|
||||||
<span v-if="item.indicate" class="indicator"><i class="ph-circle-fill"></i></span>
|
<span v-if="item.indicate" class="indicator"><i class="ph-circle-fill"></i></span>
|
||||||
</a>
|
</a>
|
||||||
<button v-else-if="item.type === 'user'" :tabindex="i" class="_button item" :class="{ active: item.active }" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
|
<button v-else-if="item.type === 'user' && !items.hidden" :tabindex="i" class="_button item" :class="{ active: item.active }" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
|
||||||
<MkAvatar :user="item.user" class="avatar"/><MkUserName :user="item.user"/>
|
<MkAvatar :user="item.user" class="avatar"/><MkUserName :user="item.user"/>
|
||||||
<span v-if="item.indicate" class="indicator"><i class="ph-circle-fill"></i></span>
|
<span v-if="item.indicate" class="indicator"><i class="ph-circle-fill"></i></span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
<span>{{ item.text }}</span>
|
<span>{{ item.text }}</span>
|
||||||
<span class="caret"><i class="ph-caret-right-bold ph-lg ph-fw ph-lg"></i></span>
|
<span class="caret"><i class="ph-caret-right-bold ph-lg ph-fw ph-lg"></i></span>
|
||||||
</button>
|
</button>
|
||||||
<button v-else :tabindex="i" class="_button item" :class="{ danger: item.danger, active: item.active }" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
|
<button v-else-if="!item.hidden" :tabindex="i" class="_button item" :class="{ danger: item.danger, active: item.active }" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
|
||||||
<i v-if="item.icon" class="ph-fw ph-lg" :class="item.icon"></i>
|
<i v-if="item.icon" class="ph-fw ph-lg" :class="item.icon"></i>
|
||||||
<MkAvatar v-if="item.avatar" :user="item.avatar" class="avatar"/>
|
<MkAvatar v-if="item.avatar" :user="item.avatar" class="avatar"/>
|
||||||
<span>{{ item.text }}</span>
|
<span>{{ item.text }}</span>
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="follow-container">
|
<div class="follow-container">
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<MkFollowButton v-if="$i != null && $i.id != user.id" :user="user" :inline="true" :transparent="false" :full="!narrow" class="koudoku"/>
|
<MkFollowButton v-if="$i != null && $i.id != user.id" :user="user" @refresh="emit('refresh')" :inline="true" :transparent="false" :full="!narrow" class="koudoku"/>
|
||||||
<button class="menu _button" @click="menu"><i class="ph-dots-three-outline-bold ph-lg"></i></button>
|
<button class="menu _button" @click="menu"><i class="ph-dots-three-outline-bold ph-lg"></i></button>
|
||||||
<!-- <MkFollowButton v-else-if="$i == null" :user="user" :remote="true" :inline="true" :transparent="false" :full="true" class="koudoku"/> -->
|
<!-- <MkFollowButton v-else-if="$i == null" :user="user" :remote="true" :inline="true" :transparent="false" :full="true" class="koudoku"/> -->
|
||||||
</div>
|
</div>
|
||||||
|
@ -142,6 +142,7 @@ import { host } from '@/config';
|
||||||
const XPhotos = defineAsyncComponent(() => import('./index.photos.vue'));
|
const XPhotos = defineAsyncComponent(() => import('./index.photos.vue'));
|
||||||
const XActivity = defineAsyncComponent(() => import('./index.activity.vue'));
|
const XActivity = defineAsyncComponent(() => import('./index.activity.vue'));
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh']);
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
user: misskey.entities.UserDetailed;
|
user: misskey.entities.UserDetailed;
|
||||||
}>(), {
|
}>(), {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<div>
|
<div>
|
||||||
<transition name="fade" mode="out-in">
|
<transition name="fade" mode="out-in">
|
||||||
<div v-if="user">
|
<div v-if="user">
|
||||||
<XHome v-if="tab === 'home'" :user="user"/>
|
<XHome v-if="tab === 'home'" :user="user" @refresh="fetchUser()"/>
|
||||||
<XReactions v-else-if="tab === 'reactions'" :user="user"/>
|
<XReactions v-else-if="tab === 'reactions'" :user="user"/>
|
||||||
<XClips v-else-if="tab === 'clips'" :user="user"/>
|
<XClips v-else-if="tab === 'clips'" :user="user"/>
|
||||||
<XPages v-else-if="tab === 'pages'" :user="user"/>
|
<XPages v-else-if="tab === 'pages'" :user="user"/>
|
||||||
|
|
|
@ -125,11 +125,20 @@ export function getUserMenu(user, router: Router = mainRouter) {
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
os.apiWithDialog(user.isBlocking ? "blocking/delete" : "blocking/create", {
|
await os.apiWithDialog(user.isBlocking ? "blocking/delete" : "blocking/create", {
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
}).then(() => {
|
})
|
||||||
user.isBlocking = !user.isBlocking;
|
user.isBlocking = !user.isBlocking;
|
||||||
});
|
await os.api(user.isBlocking ? "mute/create" : "mute/delete", {
|
||||||
|
userId: user.id,
|
||||||
|
})
|
||||||
|
user.isMuted = user.isBlocking;
|
||||||
|
if (user.isBlocking) {
|
||||||
|
await os.api('following/delete', {
|
||||||
|
userId: user.id,
|
||||||
|
});
|
||||||
|
user.isFollowing = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleSilence() {
|
async function toggleSilence() {
|
||||||
|
@ -252,6 +261,7 @@ export function getUserMenu(user, router: Router = mainRouter) {
|
||||||
{
|
{
|
||||||
icon: user.isMuted ? "ph-eye-bold ph-lg" : "ph-eye-slash-bold ph-lg",
|
icon: user.isMuted ? "ph-eye-bold ph-lg" : "ph-eye-slash-bold ph-lg",
|
||||||
text: user.isMuted ? i18n.ts.unmute : i18n.ts.mute,
|
text: user.isMuted ? i18n.ts.unmute : i18n.ts.mute,
|
||||||
|
hidden: user.isBlocking === true,
|
||||||
action: toggleMute,
|
action: toggleMute,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,6 +28,7 @@ export type MenuUser = {
|
||||||
user: Misskey.entities.User;
|
user: Misskey.entities.User;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
indicate?: boolean;
|
indicate?: boolean;
|
||||||
|
hidden?: boolean;
|
||||||
action: MenuAction;
|
action: MenuAction;
|
||||||
};
|
};
|
||||||
export type MenuSwitch = {
|
export type MenuSwitch = {
|
||||||
|
@ -43,6 +44,7 @@ export type MenuButton = {
|
||||||
indicate?: boolean;
|
indicate?: boolean;
|
||||||
danger?: boolean;
|
danger?: boolean;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
|
hidden?: boolean;
|
||||||
avatar?: Misskey.entities.User;
|
avatar?: Misskey.entities.User;
|
||||||
action: MenuAction;
|
action: MenuAction;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue