Compare commits
No commits in common. "4ea5d7c10630a8e97375cc7b1c1c70106b2c76b8" and "e91c1040e228b81e76b3b84913a7a443b17ace10" have entirely different histories.
4ea5d7c106
...
e91c1040e2
|
@ -3,7 +3,6 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "pnpm vite build --watch --mode development",
|
"watch": "pnpm vite build --watch --mode development",
|
||||||
"watchRebuild": "pnpm vite build --watch",
|
|
||||||
"build": "pnpm vite build",
|
"build": "pnpm vite build",
|
||||||
"format": "pnpm prettier --write '**/*.vue'"
|
"format": "pnpm prettier --write '**/*.vue'"
|
||||||
},
|
},
|
||||||
|
|
|
@ -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>
|
|
|
@ -7,6 +7,47 @@
|
||||||
>
|
>
|
||||||
<i class="ph-dots-three-outline ph-bold ph-lg"></i>
|
<i class="ph-dots-three-outline ph-bold ph-lg"></i>
|
||||||
</button>
|
</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
|
<button
|
||||||
v-if="$i != null && $i.id != user.id"
|
v-if="$i != null && $i.id != user.id"
|
||||||
class="kpoogebi _button follow-button"
|
class="kpoogebi _button follow-button"
|
||||||
|
@ -95,8 +136,23 @@ let hasPendingFollowRequestFromYou = $ref(
|
||||||
props.user.hasPendingFollowRequestFromYou
|
props.user.hasPendingFollowRequestFromYou
|
||||||
);
|
);
|
||||||
let wait = $ref(false);
|
let wait = $ref(false);
|
||||||
|
let waitIncoming = $ref(false);
|
||||||
const connection = stream.useChannel("main");
|
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) {
|
if (props.user.isFollowing == null) {
|
||||||
os.api("users/show", {
|
os.api("users/show", {
|
||||||
userId: props.user.id,
|
userId: props.user.id,
|
||||||
|
@ -186,6 +242,55 @@ onBeforeUnmount(() => {
|
||||||
height: 2em;
|
height: 2em;
|
||||||
vertical-align: middle;
|
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 {
|
.follow-button {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|
|
@ -220,9 +220,8 @@
|
||||||
:user="notification.user"
|
:user="notification.user"
|
||||||
:full="true"
|
:full="true"
|
||||||
:hideMenu="true"
|
:hideMenu="true"
|
||||||
/>
|
/></div
|
||||||
</div>
|
></span>
|
||||||
</span>
|
|
||||||
<span
|
<span
|
||||||
v-if="notification.type === 'followRequestAccepted'"
|
v-if="notification.type === 'followRequestAccepted'"
|
||||||
class="text"
|
class="text"
|
||||||
|
@ -235,12 +234,15 @@
|
||||||
style="opacity: 0.7"
|
style="opacity: 0.7"
|
||||||
>{{ i18n.ts.receiveFollowRequest }}
|
>{{ i18n.ts.receiveFollowRequest }}
|
||||||
<div v-if="full && !followRequestDone">
|
<div v-if="full && !followRequestDone">
|
||||||
<MkFollowApproveButton
|
<button class="_textButton" @click="acceptFollowRequest()">
|
||||||
:user="notification.user"
|
{{ i18n.ts.accept }}
|
||||||
@refresh="followRequestDone = true"
|
</button>
|
||||||
/>
|
|
|
||||||
</div>
|
<button class="_textButton" @click="rejectFollowRequest()">
|
||||||
</span>
|
{{ i18n.ts.reject }}
|
||||||
|
</button>
|
||||||
|
</div></span
|
||||||
|
>
|
||||||
<span
|
<span
|
||||||
v-if="notification.type === 'groupInvited'"
|
v-if="notification.type === 'groupInvited'"
|
||||||
class="text"
|
class="text"
|
||||||
|
@ -261,8 +263,8 @@
|
||||||
>
|
>
|
||||||
{{ i18n.ts.reject }}
|
{{ i18n.ts.reject }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div></span
|
||||||
</span>
|
>
|
||||||
<span v-if="notification.type === 'app'" class="text">
|
<span v-if="notification.type === 'app'" class="text">
|
||||||
<Mfm :text="notification.body" :nowrap="!full" />
|
<Mfm :text="notification.body" :nowrap="!full" />
|
||||||
</span>
|
</span>
|
||||||
|
@ -271,7 +273,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<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 * as misskey from "calckey-js";
|
||||||
import XReactionIcon from "@/components/MkReactionIcon.vue";
|
import XReactionIcon from "@/components/MkReactionIcon.vue";
|
||||||
import MkFollowButton from "@/components/MkFollowButton.vue";
|
import MkFollowButton from "@/components/MkFollowButton.vue";
|
||||||
|
@ -285,7 +287,6 @@ import { stream } from "@/stream";
|
||||||
import { useTooltip } from "@/scripts/use-tooltip";
|
import { useTooltip } from "@/scripts/use-tooltip";
|
||||||
import { defaultStore } from "@/store";
|
import { defaultStore } from "@/store";
|
||||||
import { instance } from "@/instance";
|
import { instance } from "@/instance";
|
||||||
import MkFollowApproveButton from "@/components/MkFollowApproveButton.vue";
|
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
@ -299,7 +300,6 @@ const props = withDefaults(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const emit = defineEmits(["refresh"]);
|
|
||||||
const elRef = ref<HTMLElement>(null);
|
const elRef = ref<HTMLElement>(null);
|
||||||
const reactionRef = ref(null);
|
const reactionRef = ref(null);
|
||||||
|
|
||||||
|
@ -342,6 +342,16 @@ onUnmounted(() => {
|
||||||
const followRequestDone = ref(false);
|
const followRequestDone = ref(false);
|
||||||
const groupInviteDone = 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 = () => {
|
const acceptGroupInvitation = () => {
|
||||||
groupInviteDone.value = true;
|
groupInviteDone.value = true;
|
||||||
os.apiWithDialog("users/groups/invitations/accept", {
|
os.apiWithDialog("users/groups/invitations/accept", {
|
||||||
|
|
|
@ -80,44 +80,30 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, onBeforeUnmount, onMounted, ref } from "vue";
|
import { ref, computed } from "vue";
|
||||||
import MkPagination from "@/components/MkPagination.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 * as os from "@/os";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
import { definePageMetadata } from "@/scripts/page-metadata";
|
import { definePageMetadata } from "@/scripts/page-metadata";
|
||||||
import { $i } from "@/account";
|
import { $i } from "@/account";
|
||||||
import { globalEvents } from "@/events";
|
|
||||||
|
|
||||||
const paginationComponent = ref<InstanceType<typeof MkPagination>>();
|
const paginationComponent = ref<InstanceType<typeof MkPagination>>();
|
||||||
|
|
||||||
const pagination = {
|
const pagination = {
|
||||||
endpoint: "following/requests/list" as const,
|
endpoint: "following/requests/list" as const,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
noPaging: true,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
globalEvents.on("followeeProcessed", () =>
|
|
||||||
paginationComponent.value.reload()
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
globalEvents.off("followeeProcessed", () =>
|
|
||||||
paginationComponent.value.reload()
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
function accept(user) {
|
function accept(user) {
|
||||||
os.api("following/requests/accept", { userId: user.id }).then(() => {
|
os.api("following/requests/accept", { userId: user.id }).then(() => {
|
||||||
globalEvents.emit("followeeProcessed", user);
|
paginationComponent.value.reload();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function reject(user) {
|
function reject(user) {
|
||||||
os.api("following/requests/reject", { userId: user.id }).then(() => {
|
os.api("following/requests/reject", { userId: user.id }).then(() => {
|
||||||
globalEvents.emit("followeeProcessed", user);
|
paginationComponent.value.reload();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,20 +69,6 @@
|
||||||
class="followed"
|
class="followed"
|
||||||
>{{ i18n.ts.followsYou }}</span
|
>{{ 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>
|
||||||
<div class="bottom">
|
<div class="bottom">
|
||||||
<span class="username"
|
<span class="username"
|
||||||
|
@ -383,7 +369,7 @@ import { getScrollPosition } from "@/scripts/scroll";
|
||||||
import { userPage } from "@/filters/user";
|
import { userPage } from "@/filters/user";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
import { $i } from "@/account";
|
import { $i } from "@/account";
|
||||||
import MkFollowApproveButton from "@/components/MkFollowApproveButton.vue";
|
import * as os from "@/os";
|
||||||
|
|
||||||
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"));
|
||||||
|
@ -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 parallaxAnimationId = $ref<null | number>(null);
|
||||||
let narrow = $ref<null | boolean>(null);
|
let narrow = $ref<null | boolean>(null);
|
||||||
let rootEl = $ref<null | HTMLElement>(null);
|
let rootEl = $ref<null | HTMLElement>(null);
|
||||||
|
|
Loading…
Reference in New Issue