Frontend: Magnetar endpoint pagination
ci/woodpecker/push/ociImagePush Pipeline was successful
Details
ci/woodpecker/push/ociImagePush Pipeline was successful
Details
This commit is contained in:
parent
80a29f771f
commit
4834daceec
|
@ -0,0 +1,399 @@
|
||||||
|
<template>
|
||||||
|
<transition :name="$store.state.animation ? 'fade' : ''" mode="out-in">
|
||||||
|
<MkLoading v-if="initialFetching" />
|
||||||
|
|
||||||
|
<MkError v-else-if="error" @retry="init()" />
|
||||||
|
|
||||||
|
<div v-else-if="empty" key="_empty_" class="empty">
|
||||||
|
<slot name="empty">
|
||||||
|
<div class="_fullinfo">
|
||||||
|
<img
|
||||||
|
src="/static-assets/badges/info.png"
|
||||||
|
class="_ghost"
|
||||||
|
alt="Error"
|
||||||
|
/>
|
||||||
|
<div>{{ i18n.ts.nothing }}</div>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else ref="rootEl" class="list">
|
||||||
|
<div
|
||||||
|
v-show="pagination.reversed && next"
|
||||||
|
key="_more_"
|
||||||
|
class="cxiknjgy _gap"
|
||||||
|
>
|
||||||
|
<MkButton
|
||||||
|
v-if="!moreFetching"
|
||||||
|
class="button"
|
||||||
|
:disabled="moreFetching"
|
||||||
|
:style="{ cursor: moreFetching ? 'wait' : 'pointer' }"
|
||||||
|
primary
|
||||||
|
@click="fetchMore"
|
||||||
|
>
|
||||||
|
{{ i18n.ts.loadMore }}
|
||||||
|
</MkButton>
|
||||||
|
<MkLoading v-else class="loading" />
|
||||||
|
</div>
|
||||||
|
<slot name="items" :items="items"></slot>
|
||||||
|
<div
|
||||||
|
v-show="!pagination.reversed && next"
|
||||||
|
key="_more_"
|
||||||
|
class="cxiknjgy _gap"
|
||||||
|
>
|
||||||
|
<MkButton
|
||||||
|
v-if="!moreFetching"
|
||||||
|
v-appear="
|
||||||
|
$store.state.enableInfiniteScroll && !disableAutoLoad
|
||||||
|
? fetchMore
|
||||||
|
: null
|
||||||
|
"
|
||||||
|
class="button"
|
||||||
|
:disabled="moreFetching"
|
||||||
|
:style="{ cursor: moreFetching ? 'wait' : 'pointer' }"
|
||||||
|
primary
|
||||||
|
@click="fetchMore"
|
||||||
|
>
|
||||||
|
{{ i18n.ts.loadMore }}
|
||||||
|
</MkButton>
|
||||||
|
<MkLoading v-else class="loading" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script
|
||||||
|
lang="ts"
|
||||||
|
setup
|
||||||
|
generic="T extends BackendApiEndpoint<
|
||||||
|
T['method'] & Method,
|
||||||
|
T['pathParams'] & string[],
|
||||||
|
T['request'],
|
||||||
|
T['response'],
|
||||||
|
T['paginated'] & true
|
||||||
|
>"
|
||||||
|
>
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
ComputedRef,
|
||||||
|
isRef,
|
||||||
|
onActivated,
|
||||||
|
onDeactivated,
|
||||||
|
ref,
|
||||||
|
watch,
|
||||||
|
} from "vue";
|
||||||
|
import * as os from "@/os";
|
||||||
|
import {
|
||||||
|
getScrollContainer,
|
||||||
|
getScrollPosition,
|
||||||
|
isTopVisible,
|
||||||
|
onScrollTop,
|
||||||
|
} from "@/scripts/scroll";
|
||||||
|
import MkButton from "@/components/MkButton.vue";
|
||||||
|
import {
|
||||||
|
BackendApiEndpoint,
|
||||||
|
Method,
|
||||||
|
PaginatedResult,
|
||||||
|
types,
|
||||||
|
} from "magnetar-common";
|
||||||
|
import { SpanFilter } from "magnetar-common/built/types/SpanFilter";
|
||||||
|
import { i18n } from "@/i18n";
|
||||||
|
|
||||||
|
type PathParams = {
|
||||||
|
[K in keyof T["pathParams"] as T["pathParams"][K] & string]:
|
||||||
|
| string
|
||||||
|
| number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Paging = {
|
||||||
|
endpoint: T;
|
||||||
|
pathParams: PathParams | ComputedRef<PathParams>;
|
||||||
|
params?: T["request"] | ComputedRef<T["request"]>;
|
||||||
|
|
||||||
|
limit?: number;
|
||||||
|
|
||||||
|
reversed?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
pagination: Paging;
|
||||||
|
disableAutoLoad?: boolean;
|
||||||
|
displayLimit?: number;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
displayLimit: 30,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(ev: "queue", count: number): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
type PageItem = PaginatedResult<T["response"]>["data"][number] & { id: string };
|
||||||
|
|
||||||
|
const rootEl = ref<HTMLElement>();
|
||||||
|
const items = ref<PageItem[]>([]);
|
||||||
|
const queue = ref<PageItem[]>([]);
|
||||||
|
const initialFetching = ref(true);
|
||||||
|
const moreFetching = ref(false);
|
||||||
|
const next = ref<URL | null>(null);
|
||||||
|
const backed = ref(false);
|
||||||
|
const isBackTop = ref(false);
|
||||||
|
const empty = computed(() => items.value.length === 0);
|
||||||
|
const error = ref(false);
|
||||||
|
|
||||||
|
const fetch = async (
|
||||||
|
pagination: SpanFilter
|
||||||
|
): Promise<PaginatedResult<T["response"]> & { data: { id: string } }[]> => {
|
||||||
|
const pathParams = isRef(props.pagination.pathParams)
|
||||||
|
? props.pagination.pathParams.value
|
||||||
|
: props.pagination.pathParams;
|
||||||
|
const params = isRef(props.pagination.params)
|
||||||
|
? props.pagination.params.value
|
||||||
|
: props.pagination.params;
|
||||||
|
|
||||||
|
return os
|
||||||
|
.magApi(
|
||||||
|
props.pagination.endpoint,
|
||||||
|
{
|
||||||
|
...params,
|
||||||
|
pagination,
|
||||||
|
limit: props.pagination.limit,
|
||||||
|
},
|
||||||
|
pathParams,
|
||||||
|
undefined
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(res) =>
|
||||||
|
res as PaginatedResult<T["response"]> &
|
||||||
|
{ data: { id: string } }[]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const init = async (): Promise<void> => {
|
||||||
|
queue.value = [];
|
||||||
|
initialFetching.value = true;
|
||||||
|
|
||||||
|
fetch({}).then(
|
||||||
|
(res) => {
|
||||||
|
items.value = props.pagination.reversed
|
||||||
|
? [...res.data].reverse()
|
||||||
|
: res.data;
|
||||||
|
next.value = res.next ?? null;
|
||||||
|
error.value = false;
|
||||||
|
initialFetching.value = false;
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
error.value = true;
|
||||||
|
initialFetching.value = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const reload = (): void => {
|
||||||
|
items.value = [];
|
||||||
|
init();
|
||||||
|
};
|
||||||
|
|
||||||
|
const refresh = async (): Promise<void> => {
|
||||||
|
fetch({}).then(
|
||||||
|
(res) => {
|
||||||
|
let ids = new Set(items.value.map((i) => i.id));
|
||||||
|
|
||||||
|
for (let i = 0; i < res.data.length; i++) {
|
||||||
|
const item = res.data[i];
|
||||||
|
if (!updateItem(item.id, (old) => item)) {
|
||||||
|
append(item);
|
||||||
|
}
|
||||||
|
ids.delete(item.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const id in ids) {
|
||||||
|
removeItem((i) => i.id === id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
error.value = true;
|
||||||
|
initialFetching.value = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchMore = async (): Promise<void> => {
|
||||||
|
if (
|
||||||
|
!next.value ||
|
||||||
|
initialFetching.value ||
|
||||||
|
moreFetching.value ||
|
||||||
|
items.value.length === 0
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (next.value.searchParams.has("pagination")) return;
|
||||||
|
|
||||||
|
const nextCursorRaw = next.value.searchParams.get("pagination") as string;
|
||||||
|
const nextCursorDecoded = {
|
||||||
|
...Object.fromEntries(new URLSearchParams(nextCursorRaw).entries()),
|
||||||
|
} as types.PaginationShape["pagination"];
|
||||||
|
|
||||||
|
moreFetching.value = true;
|
||||||
|
backed.value = true;
|
||||||
|
|
||||||
|
await fetch(nextCursorDecoded).then(
|
||||||
|
(res) => {
|
||||||
|
items.value = props.pagination.reversed
|
||||||
|
? [...res.data].reverse().concat(items.value)
|
||||||
|
: items.value.concat(res.data);
|
||||||
|
next.value = res.next ?? null;
|
||||||
|
moreFetching.value = false;
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
moreFetching.value = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const prepend = (item: PageItem): void => {
|
||||||
|
if (props.pagination.reversed) {
|
||||||
|
if (rootEl.value) {
|
||||||
|
const container = getScrollContainer(rootEl.value);
|
||||||
|
if (container == null) {
|
||||||
|
// TODO?
|
||||||
|
} else {
|
||||||
|
const pos = getScrollPosition(rootEl.value);
|
||||||
|
const viewHeight = container.clientHeight;
|
||||||
|
const height = container.scrollHeight;
|
||||||
|
const isBottom = pos + viewHeight > height - 32;
|
||||||
|
if (isBottom) {
|
||||||
|
items.value = items.value.slice(-props.displayLimit);
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// next.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
items.value.push(item);
|
||||||
|
// TODO
|
||||||
|
} else {
|
||||||
|
// 初回表示時はunshiftだけでOK
|
||||||
|
if (!rootEl.value) {
|
||||||
|
items.value.unshift(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isTop =
|
||||||
|
isBackTop.value ||
|
||||||
|
(document.body.contains(rootEl.value) &&
|
||||||
|
isTopVisible(rootEl.value));
|
||||||
|
|
||||||
|
if (isTop) {
|
||||||
|
// Prepend the item
|
||||||
|
items.value = [item, ...items.value].slice(0, props.displayLimit);
|
||||||
|
} else {
|
||||||
|
if (!queue.value.length) {
|
||||||
|
onScrollTop(rootEl.value, () => {
|
||||||
|
items.value = [
|
||||||
|
...queue.value.reverse(),
|
||||||
|
...items.value,
|
||||||
|
].slice(0, props.displayLimit);
|
||||||
|
queue.value = [];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.value = [...queue.value, item].slice(-props.displayLimit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const append = (item: PageItem): void => {
|
||||||
|
items.value.push(item);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeItem = (finder: (item: PageItem) => boolean): boolean => {
|
||||||
|
const i = items.value.findIndex(finder);
|
||||||
|
if (i === -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
items.value.splice(i, 1);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateItem = (
|
||||||
|
id: PageItem["id"],
|
||||||
|
replacer: (old: PageItem) => PageItem
|
||||||
|
): boolean => {
|
||||||
|
const i = items.value.findIndex((item) => item.id === id);
|
||||||
|
if (i === -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
items.value[i] = replacer(items.value[i]);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (props.pagination.params && isRef(props.pagination.params)) {
|
||||||
|
watch(props.pagination.params, init, { deep: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
queue,
|
||||||
|
(a, b) => {
|
||||||
|
if (a.length === 0 && b.length === 0) return;
|
||||||
|
emit("queue", queue.value.length);
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
onActivated(() => {
|
||||||
|
isBackTop.value = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
onDeactivated(() => {
|
||||||
|
isBackTop.value = window.scrollY === 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
defineSlots<{
|
||||||
|
empty(props: {}): any;
|
||||||
|
items(props: { items: PageItem[] }): any;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
items,
|
||||||
|
queue,
|
||||||
|
backed,
|
||||||
|
reload,
|
||||||
|
refresh,
|
||||||
|
prepend,
|
||||||
|
append,
|
||||||
|
removeItem,
|
||||||
|
updateItem,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: opacity 0.125s ease;
|
||||||
|
}
|
||||||
|
.fade-enter-from,
|
||||||
|
.fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cxiknjgy {
|
||||||
|
> .button {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.list > :deep(._button) {
|
||||||
|
margin-inline: auto;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
&:last-of-type:not(:first-child) {
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -3,7 +3,13 @@
|
||||||
<div
|
<div
|
||||||
class="banner"
|
class="banner"
|
||||||
:style="
|
:style="
|
||||||
user.bannerUrl ? `background-image: url(${user.bannerUrl})` : ''
|
magTransProperty(user, 'banner_url', 'bannerUrl')
|
||||||
|
? `background-image: url(${magTransProperty(
|
||||||
|
user,
|
||||||
|
'banner_url',
|
||||||
|
'bannerUrl'
|
||||||
|
)})`
|
||||||
|
: ''
|
||||||
"
|
"
|
||||||
></div>
|
></div>
|
||||||
<MagAvatarResolvingProxy
|
<MagAvatarResolvingProxy
|
||||||
|
@ -21,6 +27,7 @@
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<div v-if="user.description" class="mfm">
|
<div v-if="user.description" class="mfm">
|
||||||
<Mfm
|
<Mfm
|
||||||
|
:mm="magMaybeProperty(user, 'description_mm')"
|
||||||
:text="user.description"
|
:text="user.description"
|
||||||
:author="user"
|
:author="user"
|
||||||
:i="$i"
|
:i="$i"
|
||||||
|
@ -34,15 +41,33 @@
|
||||||
<div class="status">
|
<div class="status">
|
||||||
<div>
|
<div>
|
||||||
<p>{{ i18n.ts.notes }}</p>
|
<p>{{ i18n.ts.notes }}</p>
|
||||||
<MkNumber :value="user.notesCount" />
|
<MkNumber
|
||||||
|
:value="magTransProperty(user, 'note_count', 'notesCount')"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>{{ i18n.ts.following }}</p>
|
<p>{{ i18n.ts.following }}</p>
|
||||||
<MkNumber :value="user.followingCount" />
|
<MkNumber
|
||||||
|
:value="
|
||||||
|
magTransProperty(
|
||||||
|
user,
|
||||||
|
'following_count',
|
||||||
|
'followingCount'
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>{{ i18n.ts.followers }}</p>
|
<p>{{ i18n.ts.followers }}</p>
|
||||||
<MkNumber :value="user.followersCount" />
|
<MkNumber
|
||||||
|
:value="
|
||||||
|
magTransProperty(
|
||||||
|
user,
|
||||||
|
'follower_count',
|
||||||
|
'followersCount'
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="koudoku-button">
|
<div class="koudoku-button">
|
||||||
|
@ -58,9 +83,11 @@ import MkNumber from "@/components/MkNumber.vue";
|
||||||
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 { packed } from "magnetar-common";
|
||||||
|
import { magMaybeProperty, magTransProperty } from "@/scripts-mag/mag-util";
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
user: misskey.entities.UserDetailed;
|
user: packed.PackUserMaybeAll | misskey.entities.UserDetailed;
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,10 @@ export const userName = (user: misskey.entities.User) => {
|
||||||
return user.name || user.username;
|
return user.name || user.username;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const userPage = (user: misskey.Acct, path?, absolute = false) => {
|
export const userPage = (
|
||||||
|
user: misskey.Acct,
|
||||||
|
path?: string,
|
||||||
|
absolute = false
|
||||||
|
) => {
|
||||||
return `${absolute ? url : ""}/@${acct(user)}${path ? `/${path}` : ""}`;
|
return `${absolute ? url : ""}/@${acct(user)}${path ? `/${path}` : ""}`;
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
FrontendApiEndpoints,
|
FrontendApiEndpoints,
|
||||||
MagApiClient,
|
MagApiClient,
|
||||||
Method,
|
Method,
|
||||||
|
PaginatedResult,
|
||||||
types,
|
types,
|
||||||
} from "magnetar-common";
|
} from "magnetar-common";
|
||||||
import { magReactionToLegacy } from "@/scripts-mag/mag-util";
|
import { magReactionToLegacy } from "@/scripts-mag/mag-util";
|
||||||
|
@ -48,7 +49,9 @@ export async function magApi<
|
||||||
| number;
|
| number;
|
||||||
},
|
},
|
||||||
token?: string | null | undefined
|
token?: string | null | undefined
|
||||||
): Promise<T["response"]> {
|
): Promise<
|
||||||
|
T["paginated"] extends true ? PaginatedResult<T["response"]> : T["response"]
|
||||||
|
> {
|
||||||
pendingApiRequestsCount.value++;
|
pendingApiRequestsCount.value++;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
<MkStickyContainer>
|
<MkStickyContainer>
|
||||||
<template #header><MkPageHeader /></template>
|
<template #header><MkPageHeader /></template>
|
||||||
<MkSpacer :content-max="800">
|
<MkSpacer :content-max="800">
|
||||||
<MkPagination ref="paginationComponent" :pagination="pagination">
|
<MagPagination
|
||||||
|
ref="paginationComponent"
|
||||||
|
:pagination="followRequestPagination"
|
||||||
|
>
|
||||||
<template #empty>
|
<template #empty>
|
||||||
<div class="_fullinfo">
|
<div class="_fullinfo">
|
||||||
<img
|
<img
|
||||||
|
@ -13,88 +16,165 @@
|
||||||
<div>{{ i18n.ts.noFollowRequests }}</div>
|
<div>{{ i18n.ts.noFollowRequests }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #default="{ items }">
|
<template #items="{ items: users }">
|
||||||
<MkInfo v-if="$i?.isLocked === false" warn class="info"
|
<MkInfo v-if="$i?.isLocked === false" warn class="info"
|
||||||
>{{ i18n.ts.silencedWarning }}
|
>{{ i18n.ts.silencedWarning }}
|
||||||
</MkInfo>
|
</MkInfo>
|
||||||
<div class="mk-follow-requests">
|
<div class="mk-follow-requests">
|
||||||
<div
|
<div
|
||||||
v-for="req in items"
|
v-for="user in users"
|
||||||
:key="req.id"
|
:key="user.id"
|
||||||
class="user _panel"
|
class="user _panel"
|
||||||
>
|
>
|
||||||
<MagAvatarResolvingProxy
|
<div class="header">
|
||||||
class="avatar"
|
<MagAvatar class="avatar" :user="user" />
|
||||||
:user="req.follower"
|
|
||||||
:show-indicator="true"
|
|
||||||
disableLink
|
|
||||||
/>
|
|
||||||
<div class="body">
|
|
||||||
<div class="name">
|
<div class="name">
|
||||||
<MkA
|
<MkA
|
||||||
v-user-preview="req.follower.id"
|
v-user-preview="user.id"
|
||||||
class="name"
|
class="name"
|
||||||
:to="userPage(req.follower)"
|
:to="userPage(user)"
|
||||||
><MkUserName :user="req.follower"
|
><MkUserName :user="user"
|
||||||
/></MkA>
|
/></MkA>
|
||||||
<p class="acct">
|
<p class="acct">@{{ acct(user) }}</p>
|
||||||
@{{ acct(req.follower) }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="req.follower.description"
|
|
||||||
class="description"
|
|
||||||
:title="req.follower.description"
|
|
||||||
>
|
|
||||||
<Mfm
|
|
||||||
:text="req.follower.description"
|
|
||||||
:is-note="false"
|
|
||||||
:author="req.follower"
|
|
||||||
:i="$i"
|
|
||||||
:custom-emojis="req.follower.emojis"
|
|
||||||
:plain="true"
|
|
||||||
:nowrap="true"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button
|
<button
|
||||||
class="_button"
|
class="_button"
|
||||||
@click="accept(req.follower)"
|
:aria-label="i18n.ts.accept"
|
||||||
|
@click="accept(user)"
|
||||||
>
|
>
|
||||||
<i class="ph-check ph-bold ph-lg"></i>
|
<i class="ph-check ph-bold ph-lg"></i>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="_button"
|
class="_button"
|
||||||
@click="reject(req.follower)"
|
:aria-label="i18n.ts.reject"
|
||||||
|
@click="reject(user)"
|
||||||
>
|
>
|
||||||
<i class="ph-x ph-bold ph-lg"></i>
|
<i class="ph-x ph-bold ph-lg"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="moved" v-if="user.moved_to">
|
||||||
|
{{ i18n.ts.accountMoved }}
|
||||||
|
<MagMention
|
||||||
|
class="link"
|
||||||
|
:username="user.moved_to.username"
|
||||||
|
:host="user.moved_to.host"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="remote" v-if="user.host != null">
|
||||||
|
{{ i18n.ts.remoteUserCaution }}
|
||||||
|
<a
|
||||||
|
class="link"
|
||||||
|
:href="user.url!"
|
||||||
|
rel="nofollow noopener"
|
||||||
|
target="_blank"
|
||||||
|
>{{ i18n.ts.showOnRemote }}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="description">
|
||||||
|
<div v-if="user.description" class="mfm">
|
||||||
|
<Mfm
|
||||||
|
:mm="user.description_mm"
|
||||||
|
:text="user.description"
|
||||||
|
:author="user"
|
||||||
|
:i="$i"
|
||||||
|
:custom-emojis="user.emojis"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span v-else style="opacity: 0.7">{{
|
||||||
|
i18n.ts.noAccountDescription
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="fields">
|
||||||
|
<dl class="field">
|
||||||
|
<dt class="name">
|
||||||
|
<i
|
||||||
|
class="ph-calendar-blank ph-bold ph-lg ph-fw ph-lg"
|
||||||
|
></i>
|
||||||
|
{{ i18n.ts.registeredDate }}
|
||||||
|
</dt>
|
||||||
|
<dd class="value">
|
||||||
|
{{
|
||||||
|
new Date(
|
||||||
|
user.created_at
|
||||||
|
).toLocaleString()
|
||||||
|
}}
|
||||||
|
(<MkTime :time="user.created_at" />)
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<div v-if="user.fields?.length > 0" class="fields">
|
||||||
|
<dl
|
||||||
|
v-for="(field, i) in user.fields"
|
||||||
|
:key="i"
|
||||||
|
class="field"
|
||||||
|
>
|
||||||
|
<dt class="name">
|
||||||
|
<Mfm
|
||||||
|
:text="field.name"
|
||||||
|
:plain="true"
|
||||||
|
:custom-emojis="user.emojis"
|
||||||
|
:colored="false"
|
||||||
|
/>
|
||||||
|
</dt>
|
||||||
|
<dd class="value">
|
||||||
|
<Mfm
|
||||||
|
:mm="field.value_mm ?? undefined"
|
||||||
|
:text="field.value"
|
||||||
|
:author="user"
|
||||||
|
:i="$i"
|
||||||
|
:custom-emojis="user.emojis"
|
||||||
|
:colored="false"
|
||||||
|
/>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<div class="status">
|
||||||
|
<div>
|
||||||
|
<p>{{ i18n.ts.notes }}</p>
|
||||||
|
<MkNumber :value="user.note_count" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p>{{ i18n.ts.following }}</p>
|
||||||
|
<MkNumber :value="user.following_count" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p>{{ i18n.ts.followers }}</p>
|
||||||
|
<MkNumber :value="user.follower_count" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</MkPagination>
|
</MagPagination>
|
||||||
</MkSpacer>
|
</MkSpacer>
|
||||||
</MkStickyContainer>
|
</MkStickyContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, onBeforeUnmount, onMounted, ref } from "vue";
|
import { computed, onBeforeUnmount, onMounted, ref } from "vue";
|
||||||
import MkPagination from "@/components/MkPagination.vue";
|
|
||||||
import { acct, userPage } from "@/filters/user";
|
import { acct, userPage } 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";
|
import { globalEvents } from "@/events";
|
||||||
|
import MagPagination, { Paging } from "@/components/MagPagination.vue";
|
||||||
|
import { endpoints, types } from "magnetar-common";
|
||||||
|
import MkInfo from "@/components/MkInfo.vue";
|
||||||
|
import MkNumber from "@/components/MkNumber.vue";
|
||||||
|
import MkTime from "@/components/global/MkTime.vue";
|
||||||
|
import Mfm from "@/components/mfm.vue";
|
||||||
|
import MagMention from "@/components/MagMention.vue";
|
||||||
|
|
||||||
const paginationComponent = ref<InstanceType<typeof MkPagination>>();
|
const paginationComponent = ref<InstanceType<typeof MagPagination>>();
|
||||||
|
|
||||||
const pagination = {
|
const followRequestPagination: Paging = {
|
||||||
endpoint: "following/requests/list" as const,
|
endpoint: endpoints.GetFollowRequestsSelf,
|
||||||
limit: 10,
|
limit: 20,
|
||||||
noPaging: true,
|
pathParams: {},
|
||||||
|
params: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -113,13 +193,13 @@ onBeforeUnmount(() => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
function accept(user) {
|
function accept(user: types.Id) {
|
||||||
os.api("following/requests/accept", { userId: user.id }).then(() => {
|
os.api("following/requests/accept", { userId: user.id }).then(() => {
|
||||||
globalEvents.emit("followeeProcessed", user);
|
globalEvents.emit("followeeProcessed", user);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function reject(user) {
|
function reject(user: types.Id) {
|
||||||
os.api("following/requests/reject", { userId: user.id }).then(() => {
|
os.api("following/requests/reject", { userId: user.id }).then(() => {
|
||||||
globalEvents.emit("followeeProcessed", user);
|
globalEvents.emit("followeeProcessed", user);
|
||||||
});
|
});
|
||||||
|
@ -141,9 +221,14 @@ definePageMetadata(
|
||||||
.mk-follow-requests {
|
.mk-follow-requests {
|
||||||
> .user {
|
> .user {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 16px;
|
flex-direction: column;
|
||||||
margin: 10px 0 auto;
|
margin: 10px 0 auto;
|
||||||
|
|
||||||
|
> .header {
|
||||||
|
display: flex;
|
||||||
|
padding: 16px;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
> .avatar {
|
> .avatar {
|
||||||
display: block;
|
display: block;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
@ -153,17 +238,8 @@ definePageMetadata(
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .body {
|
|
||||||
display: flex;
|
|
||||||
width: calc(100% - 54px);
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
> .name {
|
> .name {
|
||||||
width: 45%;
|
flex-grow: 1;
|
||||||
|
|
||||||
@media (max-width: 500px) {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .name,
|
> .name,
|
||||||
> .acct {
|
> .acct {
|
||||||
|
@ -186,35 +262,103 @@ definePageMetadata(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .description {
|
|
||||||
width: 55%;
|
|
||||||
line-height: 42px;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
opacity: 0.7;
|
|
||||||
font-size: 14px;
|
|
||||||
padding-right: 40px;
|
|
||||||
padding-left: 8px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
@media (max-width: 500px) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .actions {
|
> .actions {
|
||||||
position: absolute;
|
flex-shrink: 0;
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto 0;
|
|
||||||
|
|
||||||
> button {
|
> button {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .moved,
|
||||||
|
> .remote {
|
||||||
|
padding: 16px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
border-top: solid 0.5px var(--divider);
|
||||||
|
color: var(--infoWarnFg);
|
||||||
|
|
||||||
|
> .link {
|
||||||
|
margin-left: 4px;
|
||||||
|
text-decoration: underline;
|
||||||
|
color: var(--accent);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .description {
|
||||||
|
padding: 16px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
border-top: solid 0.5px var(--divider);
|
||||||
|
|
||||||
|
> .mfm {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 10;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .fields {
|
||||||
|
border-top: solid 0.5px var(--divider);
|
||||||
|
padding: 10px 16px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
|
||||||
|
> .field {
|
||||||
|
display: flex;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .name {
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .value {
|
||||||
|
flex-grow: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .status {
|
||||||
|
padding: 10px 16px 16px;
|
||||||
|
border-top: solid 0.5px var(--divider);
|
||||||
|
|
||||||
|
> div {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
width: 33%;
|
||||||
|
|
||||||
|
> p {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.7em;
|
||||||
|
color: var(--fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
font-size: 1em;
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,52 +1,53 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<MkPagination
|
<MagPagination
|
||||||
v-slot="{ items }"
|
|
||||||
ref="list"
|
ref="list"
|
||||||
:pagination="
|
:pagination="
|
||||||
type === 'following' ? followingPagination : followersPagination
|
type === 'following' ? followingPagination : followersPagination
|
||||||
"
|
"
|
||||||
class="mk-following-or-followers"
|
class="mk-following-or-followers"
|
||||||
>
|
>
|
||||||
|
<template #items="{ items: users }">
|
||||||
<div class="users">
|
<div class="users">
|
||||||
<MkUserInfo
|
<MkUserInfo
|
||||||
v-for="user in items.map((x) =>
|
v-for="user in users as typeof endpoints.GetFollowingById.response"
|
||||||
type === 'following' ? x.followee : x.follower
|
|
||||||
)"
|
|
||||||
:key="user.id"
|
:key="user.id"
|
||||||
class="user"
|
class="user"
|
||||||
:user="user"
|
:user="user"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</MkPagination>
|
</template>
|
||||||
|
</MagPagination>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import MkUserInfo from "@/components/MkUserInfo.vue";
|
import MkUserInfo from "@/components/MkUserInfo.vue";
|
||||||
import MkPagination from "@/components/MkPagination.vue";
|
import { endpoints, packed } from "magnetar-common";
|
||||||
import { packed } from "magnetar-common";
|
import MagPagination, { Paging } from "@/components/MagPagination.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
user: packed.PackUserBase;
|
user: packed.PackUserBase;
|
||||||
type: "following" | "followers";
|
type: "following" | "followers";
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const followingPagination = {
|
const followingPagination: Paging = {
|
||||||
endpoint: "users/following" as const,
|
endpoint: endpoints.GetFollowingById,
|
||||||
limit: 20,
|
limit: 20,
|
||||||
params: computed(() => ({
|
pathParams: computed(() => ({
|
||||||
userId: props.user.id,
|
id: props.user.id,
|
||||||
})),
|
})),
|
||||||
|
params: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const followersPagination = {
|
const followersPagination: Paging = {
|
||||||
endpoint: "users/followers" as const,
|
endpoint: endpoints.GetFollowersById,
|
||||||
limit: 20,
|
limit: 20,
|
||||||
params: computed(() => ({
|
pathParams: computed(() => ({
|
||||||
userId: props.user.id,
|
id: props.user.id,
|
||||||
})),
|
})),
|
||||||
|
params: {},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ export interface BackendApiEndpoint<
|
||||||
endpoint: string;
|
endpoint: string;
|
||||||
pathParams: PP;
|
pathParams: PP;
|
||||||
request?: T;
|
request?: T;
|
||||||
response?: R;
|
response?: R & (PG extends true ? any[] : any);
|
||||||
paginated: PG;
|
paginated: PG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ export interface MagApiError {
|
||||||
|
|
||||||
export interface PaginatedResult<T> {
|
export interface PaginatedResult<T> {
|
||||||
prev?: URL;
|
prev?: URL;
|
||||||
data: T;
|
data: T & any[];
|
||||||
next?: URL;
|
next?: URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,12 @@ function extractHeaderRel(
|
||||||
const relMatch = relPar.match(/rel="(.+?)"/)?.[1];
|
const relMatch = relPar.match(/rel="(.+?)"/)?.[1];
|
||||||
|
|
||||||
if (relMatch == rel && urlMatch) {
|
if (relMatch == rel && urlMatch) {
|
||||||
|
try {
|
||||||
return new URL(urlMatch);
|
return new URL(urlMatch);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
MagApiError,
|
MagApiError,
|
||||||
MagApiErrorCode,
|
MagApiErrorCode,
|
||||||
Method,
|
Method,
|
||||||
|
PaginatedResult,
|
||||||
} from "./be-api";
|
} from "./be-api";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -19,6 +20,7 @@ export * as endpoints from "./endpoints";
|
||||||
export {
|
export {
|
||||||
Method,
|
Method,
|
||||||
BackendApiEndpoint,
|
BackendApiEndpoint,
|
||||||
|
PaginatedResult,
|
||||||
MagApiError,
|
MagApiError,
|
||||||
MagApiClient,
|
MagApiClient,
|
||||||
MagApiErrorCode,
|
MagApiErrorCode,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
import type { SpanFilter } from "./SpanFilter";
|
import type { SpanFilter } from "./SpanFilter";
|
||||||
|
|
||||||
export interface PaginationShape { pagination: SpanFilter, limit: bigint, }
|
export interface PaginationShape { pagination: SpanFilter, limit: number, }
|
|
@ -426,6 +426,14 @@ packages:
|
||||||
'@babel/types': 7.22.5
|
'@babel/types': 7.22.5
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@babel/parser@7.23.6:
|
||||||
|
resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==}
|
||||||
|
engines: {node: '>=6.0.0'}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
'@babel/types': 7.22.5
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/runtime@7.20.7:
|
/@babel/runtime@7.20.7:
|
||||||
resolution: {integrity: sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==}
|
resolution: {integrity: sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
@ -1445,7 +1453,7 @@ packages:
|
||||||
/@vue/compiler-core@3.3.4:
|
/@vue/compiler-core@3.3.4:
|
||||||
resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==}
|
resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.22.7
|
'@babel/parser': 7.23.6
|
||||||
'@vue/shared': 3.3.4
|
'@vue/shared': 3.3.4
|
||||||
estree-walker: 2.0.2
|
estree-walker: 2.0.2
|
||||||
source-map-js: 1.0.2
|
source-map-js: 1.0.2
|
||||||
|
@ -1461,7 +1469,7 @@ packages:
|
||||||
/@vue/compiler-sfc@2.7.14:
|
/@vue/compiler-sfc@2.7.14:
|
||||||
resolution: {integrity: sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==}
|
resolution: {integrity: sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.22.7
|
'@babel/parser': 7.23.6
|
||||||
postcss: 8.4.25
|
postcss: 8.4.25
|
||||||
source-map: 0.6.1
|
source-map: 0.6.1
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -1516,7 +1524,7 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/runtime-core': 3.3.4
|
'@vue/runtime-core': 3.3.4
|
||||||
'@vue/shared': 3.3.4
|
'@vue/shared': 3.3.4
|
||||||
csstype: 3.1.2
|
csstype: 3.1.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@vue/server-renderer@3.3.4(vue@3.3.4):
|
/@vue/server-renderer@3.3.4(vue@3.3.4):
|
||||||
|
@ -2793,8 +2801,8 @@ packages:
|
||||||
source-map: 0.5.7
|
source-map: 0.5.7
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/csstype@3.1.2:
|
/csstype@3.1.3:
|
||||||
resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
|
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/custom-event-polyfill@1.0.7:
|
/custom-event-polyfill@1.0.7:
|
||||||
|
@ -7444,9 +7452,10 @@ packages:
|
||||||
|
|
||||||
/vue@2.7.14:
|
/vue@2.7.14:
|
||||||
resolution: {integrity: sha512-b2qkFyOM0kwqWFuQmgd4o+uHGU7T+2z3T+WQp8UBjADfEv2n4FEMffzBmCKNP0IGzOEEfYjvtcC62xaSKeQDrQ==}
|
resolution: {integrity: sha512-b2qkFyOM0kwqWFuQmgd4o+uHGU7T+2z3T+WQp8UBjADfEv2n4FEMffzBmCKNP0IGzOEEfYjvtcC62xaSKeQDrQ==}
|
||||||
|
deprecated: Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/compiler-sfc': 2.7.14
|
'@vue/compiler-sfc': 2.7.14
|
||||||
csstype: 3.1.2
|
csstype: 3.1.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vue@3.3.4:
|
/vue@3.3.4:
|
||||||
|
|
|
@ -11,11 +11,11 @@ impl<const MIN: u64, const MAX: u64> TS for U64Range<MIN, MAX> {
|
||||||
const EXPORT_TO: Option<&'static str> = Some("bindings/util/u64_range.ts");
|
const EXPORT_TO: Option<&'static str> = Some("bindings/util/u64_range.ts");
|
||||||
|
|
||||||
fn decl() -> String {
|
fn decl() -> String {
|
||||||
<u64 as TS>::decl()
|
<usize as TS>::decl()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name() -> String {
|
fn name() -> String {
|
||||||
<u64 as TS>::name()
|
<usize as TS>::name()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dependencies() -> Vec<ts_rs::Dependency> {
|
fn dependencies() -> Vec<ts_rs::Dependency> {
|
||||||
|
|
Loading…
Reference in New Issue