Compare commits

..

No commits in common. "4ea5d7c10630a8e97375cc7b1c1c70106b2c76b8" and "e91c1040e228b81e76b3b84913a7a443b17ace10" have entirely different histories.

6 changed files with 142 additions and 132 deletions

View File

@ -3,7 +3,6 @@
"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

@ -1,84 +0,0 @@
<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,6 +7,47 @@
>
<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"
@ -95,8 +136,23 @@ 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,
@ -186,6 +242,55 @@ 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,9 +220,8 @@
:user="notification.user"
:full="true"
:hideMenu="true"
/>
</div>
</span>
/></div
></span>
<span
v-if="notification.type === 'followRequestAccepted'"
class="text"
@ -235,12 +234,15 @@
style="opacity: 0.7"
>{{ i18n.ts.receiveFollowRequest }}
<div v-if="full && !followRequestDone">
<MkFollowApproveButton
:user="notification.user"
@refresh="followRequestDone = true"
/>
</div>
</span>
<button class="_textButton" @click="acceptFollowRequest()">
{{ i18n.ts.accept }}
</button>
|
<button class="_textButton" @click="rejectFollowRequest()">
{{ i18n.ts.reject }}
</button>
</div></span
>
<span
v-if="notification.type === 'groupInvited'"
class="text"
@ -261,8 +263,8 @@
>
{{ i18n.ts.reject }}
</button>
</div>
</span>
</div></span
>
<span v-if="notification.type === 'app'" class="text">
<Mfm :text="notification.body" :nowrap="!full" />
</span>
@ -271,7 +273,7 @@
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref, watch } from "vue";
import { ref, onMounted, onUnmounted, watch } from "vue";
import * as misskey from "calckey-js";
import XReactionIcon from "@/components/MkReactionIcon.vue";
import MkFollowButton from "@/components/MkFollowButton.vue";
@ -285,7 +287,6 @@ 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<{
@ -299,7 +300,6 @@ const props = withDefaults(
}
);
const emit = defineEmits(["refresh"]);
const elRef = ref<HTMLElement>(null);
const reactionRef = ref(null);
@ -342,6 +342,16 @@ 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,44 +80,30 @@
</template>
<script lang="ts" setup>
import { computed, onBeforeUnmount, onMounted, ref } from "vue";
import { ref, computed } from "vue";
import MkPagination from "@/components/MkPagination.vue";
import { acct, userPage } from "@/filters/user";
import { userPage, acct } 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(() => {
globalEvents.emit("followeeProcessed", user);
paginationComponent.value.reload();
});
}
function reject(user) {
os.api("following/requests/reject", { userId: user.id }).then(() => {
globalEvents.emit("followeeProcessed", user);
paginationComponent.value.reload();
});
}

View File

@ -69,20 +69,6 @@
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"
@ -383,7 +369,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";
import * as os from "@/os";
const XPhotos = defineAsyncComponent(() => import("./index.photos.vue"));
const XActivity = defineAsyncComponent(() => import("./index.activity.vue"));
@ -396,6 +382,14 @@ const props = withDefaults(
{}
);
function accept(user) {
os.api("following/requests/accept", { userId: user.id });
}
function reject(user) {
os.api("following/requests/reject", { userId: user.id }).then();
}
let parallaxAnimationId = $ref<null | number>(null);
let narrow = $ref<null | boolean>(null);
let rootEl = $ref<null | HTMLElement>(null);