Frontend: Follow request cleanup
ci/woodpecker/push/ociImagePush Pipeline was successful Details

This commit is contained in:
Natty 2023-09-08 19:09:19 +02:00
parent 1b87a57b8c
commit 4ea5d7c106
Signed by: natty
GPG Key ID: BF6CB659ADEE60EC
6 changed files with 132 additions and 133 deletions

View File

@ -3,6 +3,7 @@
"private": true,
"scripts": {
"watch": "pnpm vite build --watch --mode development",
"watchRebuild": "pnpm vite build --watch",
"build": "pnpm vite build",
"format": "pnpm prettier --write '**/*.vue'"
},

View File

@ -0,0 +1,84 @@
<template>
<template v-if="waitIncoming">
<i class="ph-circle-notch ph-bold ph-lg fa-pulse ph-fw ph-lg"></i>
</template>
<template v-else>
<button
class="_textButton"
:disabled="waitIncoming"
@click.stop="accept(user)"
>
<i class="ph-check ph-bold ph-lg"></i>
<span class="follow-approve-label">
{{ i18n.ts.accept }}
</span>
</button>
|
<button
class="_textButton"
:disabled="waitIncoming"
@click.stop="reject(user)"
>
<i class="ph-x ph-bold ph-lg"></i>
<span class="follow-approve-label">
{{ i18n.ts.reject }}
</span>
</button>
</template>
</template>
<script lang="ts" setup>
import { onBeforeUnmount, onMounted } from "vue";
import type * as Misskey from "calckey-js";
import * as os from "@/os";
import { i18n } from "@/i18n";
import { useRouter } from "@/router";
import { stream } from "@/stream";
import { globalEvents } from "@/events";
const router = useRouter();
const emit = defineEmits(["refresh"]);
const props = defineProps<{
user: Misskey.entities.User;
}>();
let state = $ref(i18n.ts.processing);
const connection = stream.useChannel("main");
let waitIncoming = $ref(false);
function accept(user: Misskey.entities.User) {
waitIncoming = true;
os.api("following/requests/accept", { userId: user.id }).then(() => {
globalEvents.emit("followeeProcessed", user);
});
}
function reject(user: Misskey.entities.User) {
waitIncoming = true;
os.api("following/requests/reject", { userId: user.id }).then(() => {
globalEvents.emit("followeeProcessed", user);
});
}
function onFolloweeChange(user: Misskey.entities.User) {
if (user.id === props.user.id) {
emit("refresh");
}
}
onMounted(() => {
globalEvents.on("followeeProcessed", () => onFolloweeChange(props.user));
});
onBeforeUnmount(() => {
globalEvents.off("followeeProcessed", () => onFolloweeChange(props.user));
});
</script>
<style lang="scss" scoped>
.follow-approve-label {
padding-left: 0.25em;
}
</style>

View File

@ -7,47 +7,6 @@
>
<i class="ph-dots-three-outline ph-bold ph-lg"></i>
</button>
<span
class="follow-menu"
:class="{
large,
full,
}"
v-if="
$i != null && $i.id != user.id && user.hasPendingFollowRequestToYou
"
>
<span v-if="full">
{{ i18n.ts.followRequestYou }}
</span>
<span v-else>
<i
class="ph-hand-waving ph-bold ph-lg"
:aria-label="i18n.ts.followRequestYou"
></i>
</span>
<template v-if="waitIncoming">
<i class="ph-circle-notch ph-bold ph-lg fa-pulse"></i>
</template>
<template v-else>
<button
class="_button follow-incoming"
:disabled="waitIncoming"
@click.stop="accept(user)"
v-tooltip="i18n.ts.accept"
>
<i class="ph-check ph-bold ph-lg"></i>
</button>
<button
class="_button follow-incoming"
:disabled="waitIncoming"
@click.stop="reject(user)"
v-tooltip="i18n.ts.reject"
>
<i class="ph-x ph-bold ph-lg"></i>
</button>
</template>
</span>
<button
v-if="$i != null && $i.id != user.id"
class="kpoogebi _button follow-button"
@ -136,23 +95,8 @@ let hasPendingFollowRequestFromYou = $ref(
props.user.hasPendingFollowRequestFromYou
);
let wait = $ref(false);
let waitIncoming = $ref(false);
const connection = stream.useChannel("main");
function accept(user) {
waitIncoming = true;
os.api("following/requests/accept", { userId: user.id }).then(() => {
emit("refresh");
});
}
function reject(user) {
waitIncoming = true;
os.api("following/requests/reject", { userId: user.id }).then(() => {
emit("refresh");
});
}
if (props.user.isFollowing == null) {
os.api("users/show", {
userId: props.user.id,
@ -242,55 +186,6 @@ onBeforeUnmount(() => {
height: 2em;
vertical-align: middle;
}
.follow-menu {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: var(--accent);
border: solid 1px var(--accent);
padding: 0;
font-size: 16px;
height: 2em;
border-radius: 100px;
background: var(--bg);
vertical-align: middle;
&.full {
padding: 0.2em 0.7em;
font-size: 14px;
}
&.large {
font-size: 16px;
height: 38px;
padding: 0 12px 0 16px;
}
&.follow-incoming {
margin: 0 0.5em;
border-inline-start: solid 1px var(--accent);
&.active {
color: var(--fgOnAccent);
background: var(--accent);
&:hover {
background: var(--accentLighten);
border-color: var(--accentLighten);
}
&:active {
background: var(--accentDarken);
border-color: var(--accentDarken);
}
}
}
}
.follow-button {
position: relative;
display: inline-flex;

View File

@ -220,8 +220,9 @@
:user="notification.user"
:full="true"
:hideMenu="true"
/></div
></span>
/>
</div>
</span>
<span
v-if="notification.type === 'followRequestAccepted'"
class="text"
@ -234,15 +235,12 @@
style="opacity: 0.7"
>{{ i18n.ts.receiveFollowRequest }}
<div v-if="full && !followRequestDone">
<button class="_textButton" @click="acceptFollowRequest()">
{{ i18n.ts.accept }}
</button>
|
<button class="_textButton" @click="rejectFollowRequest()">
{{ i18n.ts.reject }}
</button>
</div></span
>
<MkFollowApproveButton
:user="notification.user"
@refresh="followRequestDone = true"
/>
</div>
</span>
<span
v-if="notification.type === 'groupInvited'"
class="text"
@ -263,8 +261,8 @@
>
{{ i18n.ts.reject }}
</button>
</div></span
>
</div>
</span>
<span v-if="notification.type === 'app'" class="text">
<Mfm :text="notification.body" :nowrap="!full" />
</span>
@ -273,7 +271,7 @@
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, watch } from "vue";
import { onMounted, onUnmounted, ref, watch } from "vue";
import * as misskey from "calckey-js";
import XReactionIcon from "@/components/MkReactionIcon.vue";
import MkFollowButton from "@/components/MkFollowButton.vue";
@ -287,6 +285,7 @@ import { stream } from "@/stream";
import { useTooltip } from "@/scripts/use-tooltip";
import { defaultStore } from "@/store";
import { instance } from "@/instance";
import MkFollowApproveButton from "@/components/MkFollowApproveButton.vue";
const props = withDefaults(
defineProps<{
@ -300,6 +299,7 @@ const props = withDefaults(
}
);
const emit = defineEmits(["refresh"]);
const elRef = ref<HTMLElement>(null);
const reactionRef = ref(null);
@ -342,16 +342,6 @@ onUnmounted(() => {
const followRequestDone = ref(false);
const groupInviteDone = ref(false);
const acceptFollowRequest = () => {
followRequestDone.value = true;
os.api("following/requests/accept", { userId: props.notification.user.id });
};
const rejectFollowRequest = () => {
followRequestDone.value = true;
os.api("following/requests/reject", { userId: props.notification.user.id });
};
const acceptGroupInvitation = () => {
groupInviteDone.value = true;
os.apiWithDialog("users/groups/invitations/accept", {

View File

@ -80,30 +80,44 @@
</template>
<script lang="ts" setup>
import { ref, computed } from "vue";
import { computed, onBeforeUnmount, onMounted, ref } from "vue";
import MkPagination from "@/components/MkPagination.vue";
import { userPage, acct } from "@/filters/user";
import { acct, userPage } from "@/filters/user";
import * as os from "@/os";
import { i18n } from "@/i18n";
import { definePageMetadata } from "@/scripts/page-metadata";
import { $i } from "@/account";
import { globalEvents } from "@/events";
const paginationComponent = ref<InstanceType<typeof MkPagination>>();
const pagination = {
endpoint: "following/requests/list" as const,
limit: 10,
noPaging: true,
};
onMounted(() => {
globalEvents.on("followeeProcessed", () =>
paginationComponent.value.reload()
);
});
onBeforeUnmount(() => {
globalEvents.off("followeeProcessed", () =>
paginationComponent.value.reload()
);
});
function accept(user) {
os.api("following/requests/accept", { userId: user.id }).then(() => {
paginationComponent.value.reload();
globalEvents.emit("followeeProcessed", user);
});
}
function reject(user) {
os.api("following/requests/reject", { userId: user.id }).then(() => {
paginationComponent.value.reload();
globalEvents.emit("followeeProcessed", user);
});
}

View File

@ -69,6 +69,20 @@
class="followed"
>{{ i18n.ts.followsYou }}</span
>
<span
v-if="
$i &&
$i.id != user.id &&
user.hasPendingFollowRequestToYou
"
class="followed"
>{{ i18n.ts.followRequestYou }}:
<MkFollowApproveButton
:user="user"
@refresh="emit('refresh')"
class="koudoku"
/>
</span>
</div>
<div class="bottom">
<span class="username"
@ -369,6 +383,7 @@ import { getScrollPosition } from "@/scripts/scroll";
import { userPage } from "@/filters/user";
import { i18n } from "@/i18n";
import { $i } from "@/account";
import MkFollowApproveButton from "@/components/MkFollowApproveButton.vue";
const XPhotos = defineAsyncComponent(() => import("./index.photos.vue"));
const XActivity = defineAsyncComponent(() => import("./index.activity.vue"));