wip
This commit is contained in:
parent
5e9d36e9c5
commit
17d71fa0ad
@ -31,12 +31,6 @@ export default defineComponent({
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
itemsContainer: {
|
||||
type: Object as PropType<HTMLElement | null>,
|
||||
required: false,
|
||||
nullable: true,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
|
||||
setup(props, { slots, expose, emit }) {
|
||||
@ -97,11 +91,6 @@ export default defineComponent({
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
const el = getCurrentInstance()?.vnode.el;
|
||||
emit('update:itemsContainer', el ? markRaw(el) : null);
|
||||
});
|
||||
|
||||
function onBeforeLeave(el: HTMLElement) {
|
||||
el.style.top = `${el.offsetTop}px`;
|
||||
el.style.left = `${el.offsetLeft}px`;
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #default="{ items: notes, itemsContainerWrapped }">
|
||||
<template #default="{ items: notes }">
|
||||
<div class="giivymft" :class="{ noGap }">
|
||||
<XList
|
||||
ref="notes"
|
||||
@ -17,7 +17,6 @@
|
||||
:reversed="pagination.reversed"
|
||||
:no-gap="noGap"
|
||||
:ad="true"
|
||||
v-model:itemsContainer="itemsContainerWrapped.v.value"
|
||||
class="notes"
|
||||
>
|
||||
<XNote :key="note._featuredId_ || note._prId_ || note.id" class="qtqtichx" :note="note"/>
|
||||
|
@ -7,8 +7,8 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #default="{ items: notifications, itemsContainerWrapped }">
|
||||
<XList v-slot="{ item: notification }" class="elsfgstc" :items="notifications" :no-gap="true" v-model:itemsContainer="itemsContainerWrapped.v.value">
|
||||
<template #default="{ items: notifications }">
|
||||
<XList v-slot="{ item: notification }" class="elsfgstc" :items="notifications" :no-gap="true">
|
||||
<XNote v-if="['reply', 'quote', 'mention'].includes(notification.type)" :key="notification.id" :note="notification.note"/>
|
||||
<XNotification v-else :key="notification.id" :notification="notification" :with-time="true" :full="true" class="_panel notification"/>
|
||||
</XList>
|
||||
|
@ -20,7 +20,7 @@
|
||||
</MkButton>
|
||||
<MkLoading v-else class="loading"/>
|
||||
</div>
|
||||
<slot :items="items" :fetching="fetching || moreFetching" :itemsContainer="itemsContainer" :itemsContainerWrapped="itemsContainerWrapped"></slot>
|
||||
<slot :items="items" :fetching="fetching || moreFetching"></slot>
|
||||
<div v-if="!pagination.reversed" v-show="more" key="_more_" class="cxiknjgy _gap">
|
||||
<MkButton v-if="!moreFetching" v-appear="(enableInfiniteScroll && !props.disableAutoLoad) ? fetchMore : null" class="button" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary @click="fetchMore">
|
||||
{{ $ts.loadMore }}
|
||||
@ -79,27 +79,8 @@ const emit = defineEmits<{
|
||||
|
||||
let rootEl = $ref<HTMLElement>();
|
||||
|
||||
/*
|
||||
* itemsContainer: itemsの実体DOMsの親コンテナ(=v-forの直上)のHTMLElement
|
||||
*
|
||||
* IntersectionObserverを使用してスクロールのパフォーマンスを向上させるため必要
|
||||
* この中の最初の要素を評価するので、順番を反転したり変えたりしてはいけない
|
||||
*
|
||||
* これがundefinedのままの場合はrootElにフォールバックする
|
||||
* つまりrootElがitemsの実体DOMsの親であるとする
|
||||
*
|
||||
* 自動ロードやストリーミングでの追加がなければあまり関係ない
|
||||
*/
|
||||
let itemsContainer = $ref<HTMLElement | null>();
|
||||
/*
|
||||
* date-separated-listとやり取りするために入れ子にしたオブジェクトを用意する
|
||||
* slotの中身から変数を直接書き込むことができないため
|
||||
*/
|
||||
const itemsContainerWrapped = { v: $$(itemsContainer) };
|
||||
|
||||
/*
|
||||
* 遡り中かどうか
|
||||
* = (itemsContainer || rootEl).children.item(0) が画面内に入ったかどうか
|
||||
*/
|
||||
let backed = $ref(false);
|
||||
|
||||
@ -121,24 +102,20 @@ const {
|
||||
const contentEl = $computed(() => props.pagination.pageEl || rootEl);
|
||||
const scrollableElement = $computed(() => getScrollContainer(contentEl));
|
||||
|
||||
const observer = new IntersectionObserver(entries => {
|
||||
if (entries.some(entry => entry.isIntersecting)) {
|
||||
backed = false;
|
||||
} else {
|
||||
backed = true;
|
||||
}
|
||||
});
|
||||
const observer = $computed(() => new IntersectionObserver(entries => {
|
||||
backed = props.pagination.reversed ? !entries[0].isIntersecting : entries[0].isIntersecting;
|
||||
}, {
|
||||
root: scrollableElement,
|
||||
rootMargin: props.pagination.reversed ? "-100% 0px 100% 0px" : "100% 0px -100% 0px",
|
||||
threshold: 0.01,
|
||||
}));
|
||||
|
||||
watch([$$(itemsContainer), $$(rootEl)], observeLatestElement);
|
||||
watch(items, observeLatestElement, { deep: true });
|
||||
|
||||
function observeLatestElement() {
|
||||
watch($$(contentEl), () => {
|
||||
observer.disconnect();
|
||||
nextTick(() => {
|
||||
const latestEl = (itemsContainer || rootEl)?.children.item(0);
|
||||
if (latestEl) observer.observe(latestEl);
|
||||
if (contentEl) observer.observe(contentEl);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
watch([$$(backed), $$(contentEl)], () => {
|
||||
if (!backed) {
|
||||
|
@ -7,8 +7,8 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #default="{ items: users, itemsContainer }">
|
||||
<div class="efvhhmdq" ref="itemsContainer">
|
||||
<template #default="{ items: users }">
|
||||
<div class="efvhhmdq">
|
||||
<MkUserInfo v-for="user in users" :key="user.id" class="user" :user="user"/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -19,8 +19,8 @@
|
||||
</div>
|
||||
<MkPagination ref="emojisPaginationComponent" :pagination="pagination">
|
||||
<template #empty><span>{{ $ts.noCustomEmojis }}</span></template>
|
||||
<template v-slot="{items, itemsContainer}">
|
||||
<div class="ldhfsamy" ref="itemsContainer">
|
||||
<template v-slot="{items}">
|
||||
<div class="ldhfsamy">
|
||||
<button v-for="emoji in items" :key="emoji.id" class="emoji _panel _button" :class="{ selected: selectedEmojis.includes(emoji.id) }" @click="selectMode ? toggleSelect(emoji) : edit(emoji)">
|
||||
<img :src="emoji.url" class="img" :alt="emoji.name"/>
|
||||
<div class="body">
|
||||
@ -45,8 +45,8 @@
|
||||
</FormSplit>
|
||||
<MkPagination :pagination="remotePagination">
|
||||
<template #empty><span>{{ $ts.noCustomEmojis }}</span></template>
|
||||
<template v-slot="{items, itemsContainer}">
|
||||
<div class="ldhfsamy" ref="itemsContainer">
|
||||
<template v-slot="{items}">
|
||||
<div class="ldhfsamy">
|
||||
<div v-for="emoji in items" :key="emoji.id" class="emoji _panel _button" @click="remoteMenu(emoji, $event)">
|
||||
<img :src="emoji.url" class="img" :alt="emoji.name"/>
|
||||
<div class="body">
|
||||
|
@ -8,8 +8,8 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #default="{ items, itemsContainerWrapped }">
|
||||
<XList v-slot="{ item }" :items="items" :direction="'down'" :no-gap="false" :ad="false" v-model:itemsContainer="itemsContainerWrapped.v.value">
|
||||
<template #default="{ items }">
|
||||
<XList v-slot="{ item }" :items="items" :direction="'down'" :no-gap="false" :ad="false">
|
||||
<XNote :key="item.id" :note="item.note" :class="$style.note"/>
|
||||
</XList>
|
||||
</template>
|
||||
|
@ -41,8 +41,8 @@
|
||||
</FormSplit>
|
||||
</div>
|
||||
|
||||
<MkPagination v-slot="{items, itemsContainer}" ref="instances" :key="host + state" :pagination="pagination">
|
||||
<div class="dqokceoi" ref="itemsContainer">
|
||||
<MkPagination v-slot="{items}" ref="instances" :key="host + state" :pagination="pagination">
|
||||
<div class="dqokceoi">
|
||||
<MkA v-for="instance in items" :key="instance.id" class="instance" :to="`/instance-info/${instance.host}`">
|
||||
<div class="host"><img :src="instance.faviconUrl">{{ instance.host }}</div>
|
||||
<div class="table">
|
||||
|
@ -7,8 +7,8 @@
|
||||
<div>{{ $ts.noFollowRequests }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{items, itemsContainer}">
|
||||
<div class="mk-follow-requests" ref="itemsContainer">
|
||||
<template v-slot="{items}">
|
||||
<div class="mk-follow-requests">
|
||||
<div v-for="req in items" :key="req.id" class="user _panel">
|
||||
<MkAvatar class="avatar" :user="req.follower" :show-indicator="true"/>
|
||||
<div class="body">
|
||||
|
@ -9,32 +9,32 @@
|
||||
<div v-if="tab === 'explore'">
|
||||
<MkFolder class="_gap">
|
||||
<template #header><i class="fas fa-clock"></i>{{ $ts.recentPosts }}</template>
|
||||
<MkPagination v-slot="{items, itemsContainer}" :pagination="recentPostsPagination" :disable-auto-load="true">
|
||||
<div class="vfpdbgtk" ref="itemsContainer">
|
||||
<MkPagination v-slot="{items}" :pagination="recentPostsPagination" :disable-auto-load="true">
|
||||
<div class="vfpdbgtk">
|
||||
<MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/>
|
||||
</div>
|
||||
</MkPagination>
|
||||
</MkFolder>
|
||||
<MkFolder class="_gap">
|
||||
<template #header><i class="fas fa-fire-alt"></i>{{ $ts.popularPosts }}</template>
|
||||
<MkPagination v-slot="{items, itemsContainer}" :pagination="popularPostsPagination" :disable-auto-load="true">
|
||||
<div class="vfpdbgtk" ref="itemsContainer">
|
||||
<MkPagination v-slot="{items}" :pagination="popularPostsPagination" :disable-auto-load="true">
|
||||
<div class="vfpdbgtk">
|
||||
<MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/>
|
||||
</div>
|
||||
</MkPagination>
|
||||
</MkFolder>
|
||||
</div>
|
||||
<div v-else-if="tab === 'liked'">
|
||||
<MkPagination v-slot="{items, itemsContainer}" :pagination="likedPostsPagination">
|
||||
<div class="vfpdbgtk" ref="itemsContainer">
|
||||
<MkPagination v-slot="{items}" :pagination="likedPostsPagination">
|
||||
<div class="vfpdbgtk">
|
||||
<MkGalleryPostPreview v-for="like in items" :key="like.id" :post="like.post" class="post"/>
|
||||
</div>
|
||||
</MkPagination>
|
||||
</div>
|
||||
<div v-else-if="tab === 'my'">
|
||||
<MkA to="/gallery/new" class="_link" style="margin: 16px;"><i class="fas fa-plus"></i> {{ $ts.postToGallery }}</MkA>
|
||||
<MkPagination v-slot="{items, itemsContainer}" :pagination="myPostsPagination">
|
||||
<div class="vfpdbgtk" ref="itemsContainer">
|
||||
<MkPagination v-slot="{items}" :pagination="myPostsPagination">
|
||||
<div class="vfpdbgtk">
|
||||
<MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/>
|
||||
</div>
|
||||
</MkPagination>
|
||||
|
@ -36,8 +36,8 @@
|
||||
<MkAd :prefer="['horizontal', 'horizontal-big']"/>
|
||||
<MkContainer :max-height="300" :foldable="true" class="other">
|
||||
<template #header><i class="fas fa-clock"></i> {{ $ts.recentPosts }}</template>
|
||||
<MkPagination v-slot="{items, itemsContainer}" :pagination="otherPostsPagination">
|
||||
<div class="sdrarzaf" ref="itemsContainer">
|
||||
<MkPagination v-slot="{items}" :pagination="otherPostsPagination">
|
||||
<div class="sdrarzaf">
|
||||
<MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/>
|
||||
</div>
|
||||
</MkPagination>
|
||||
|
@ -14,13 +14,12 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #default="{ items: messages, fetching, itemsContainerWrapped }">
|
||||
<template #default="{ items: messages, fetching }">
|
||||
<XList
|
||||
v-if="messages.length > 0"
|
||||
v-slot="{ item: message }"
|
||||
:class="{ messages: true, 'deny-move-transition': fetching }"
|
||||
:items="messages"
|
||||
v-model:itemsContainer="itemsContainerWrapped.v.value"
|
||||
direction="up"
|
||||
reversed
|
||||
>
|
||||
|
@ -13,8 +13,8 @@
|
||||
<FormSection>
|
||||
<template #label>{{ $ts.signinHistory }}</template>
|
||||
<MkPagination :pagination="pagination">
|
||||
<template v-slot="{items, itemsContainer}">
|
||||
<div ref="itemsContainer">
|
||||
<template v-slot="{items}">
|
||||
<div>
|
||||
<div v-for="item in items" :key="item.id" v-panel class="timnmucd">
|
||||
<header>
|
||||
<i v-if="item.success" class="fas fa-check icon succ"></i>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<MkPagination v-slot="{items, itemsContainer}" ref="list" :pagination="type === 'following' ? followingPagination : followersPagination" class="mk-following-or-followers">
|
||||
<div class="users _isolated" ref="itemsContainer">
|
||||
<MkPagination v-slot="{items}" ref="list" :pagination="type === 'following' ? followingPagination : followersPagination" class="mk-following-or-followers">
|
||||
<div class="users _isolated">
|
||||
<MkUserInfo v-for="user in items.map(x => type === 'following' ? x.followee : x.follower)" :key="user.id" class="user" :user="user"/>
|
||||
</div>
|
||||
</MkPagination>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<MkPagination v-slot="{items, itemsContainer}" :pagination="pagination">
|
||||
<div class="jrnovfpt" ref="itemsContainer">
|
||||
<MkPagination v-slot="{items}" :pagination="pagination">
|
||||
<div class="jrnovfpt">
|
||||
<MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/>
|
||||
</div>
|
||||
</MkPagination>
|
||||
|
Loading…
Reference in New Issue
Block a user