test
This commit is contained in:
parent
48d3341462
commit
9f246e3dc7
1 changed files with 54 additions and 19 deletions
|
@ -54,7 +54,17 @@ const APPEAR_MINIMUM_INTERVAL = 600;
|
||||||
|
|
||||||
export type Paging<E extends keyof misskey.Endpoints = keyof misskey.Endpoints> = {
|
export type Paging<E extends keyof misskey.Endpoints = keyof misskey.Endpoints> = {
|
||||||
endpoint: E;
|
endpoint: E;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一度にAPIへ取得する件数
|
||||||
|
*/
|
||||||
limit: number;
|
limit: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* タイムラインに表示する最大件数
|
||||||
|
*/
|
||||||
|
displayLimit?: number;
|
||||||
|
|
||||||
params?: misskey.Endpoints[E]['req'] | ComputedRef<misskey.Endpoints[E]['req']>;
|
params?: misskey.Endpoints[E]['req'] | ComputedRef<misskey.Endpoints[E]['req']>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,9 +99,7 @@ import { infoImageUrl } from '@/instance';
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
pagination: Paging;
|
pagination: Paging;
|
||||||
disableAutoLoad?: boolean;
|
disableAutoLoad?: boolean;
|
||||||
displayLimit?: number;
|
|
||||||
}>(), {
|
}>(), {
|
||||||
displayLimit: 20,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
@ -124,17 +132,23 @@ const offset = ref(0);
|
||||||
*/
|
*/
|
||||||
const fetching = ref(true);
|
const fetching = ref(true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* onActivatedでtrue, onDeactivatedでfalseになる
|
||||||
|
*/
|
||||||
|
const active = ref(false);
|
||||||
|
|
||||||
const moreFetching = ref(false);
|
const moreFetching = ref(false);
|
||||||
const more = ref(false);
|
const more = ref(false);
|
||||||
const preventAppearFetchMore = ref(false);
|
const preventAppearFetchMore = ref(false);
|
||||||
const preventAppearFetchMoreTimer = ref<number | null>(null);
|
const preventAppearFetchMoreTimer = ref<number | null>(null);
|
||||||
const isBackTop = ref(false);
|
|
||||||
const empty = computed(() => items.value.size === 0);
|
const empty = computed(() => items.value.size === 0);
|
||||||
const error = ref(false);
|
const error = ref(false);
|
||||||
const {
|
const {
|
||||||
enableInfiniteScroll,
|
enableInfiniteScroll,
|
||||||
} = defaultStore.reactiveState;
|
} = defaultStore.reactiveState;
|
||||||
|
|
||||||
|
const displayLimit = computed(() => props.pagination.displayLimit ?? props.pagination.limit * 2);
|
||||||
|
|
||||||
const contentEl = $computed(() => props.pagination.pageEl ?? rootEl);
|
const contentEl = $computed(() => props.pagination.pageEl ?? rootEl);
|
||||||
const scrollableElement = $computed(() => contentEl ? getScrollContainer(contentEl) : document.body);
|
const scrollableElement = $computed(() => contentEl ? getScrollContainer(contentEl) : document.body);
|
||||||
|
|
||||||
|
@ -339,9 +353,9 @@ const appearFetchMoreAhead = async (): Promise<void> => {
|
||||||
fetchMoreAppearTimeout();
|
fetchMoreAppearTimeout();
|
||||||
};
|
};
|
||||||
|
|
||||||
const isTop = (): boolean => isBackTop.value || (props.pagination.reversed ? isBottomVisible : isTopVisible)(contentEl!, TOLERANCE);
|
const isTop = (): boolean => (props.pagination.reversed ? isBottomVisible : isTopVisible)(contentEl!, TOLERANCE);
|
||||||
|
|
||||||
watch(visibility, () => {
|
function visibilityChange() {
|
||||||
if (visibility.value === 'hidden') {
|
if (visibility.value === 'hidden') {
|
||||||
timerForSetPause = window.setTimeout(() => {
|
timerForSetPause = window.setTimeout(() => {
|
||||||
isPausingUpdate = true;
|
isPausingUpdate = true;
|
||||||
|
@ -354,13 +368,24 @@ watch(visibility, () => {
|
||||||
timerForSetPause = null;
|
timerForSetPause = null;
|
||||||
} else {
|
} else {
|
||||||
isPausingUpdate = false;
|
isPausingUpdate = false;
|
||||||
if (isTop()) {
|
if (isTop() && active.value) {
|
||||||
executeQueue();
|
executeQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onActivated(() => {
|
||||||
|
active.value = true;
|
||||||
|
visibilityChange();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onDeactivated(() => {
|
||||||
|
active.value = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(visibility, visibilityChange);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 最新のものとして1つだけアイテムを追加する
|
* 最新のものとして1つだけアイテムを追加する
|
||||||
* ストリーミングから降ってきたアイテムはこれで追加する
|
* ストリーミングから降ってきたアイテムはこれで追加する
|
||||||
|
@ -373,19 +398,28 @@ const prepend = (item: MisskeyEntity): void => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTop() && !isPausingUpdate) unshiftItems([item]);
|
if (
|
||||||
else prependQueue(item);
|
isTop() && // 先頭に表示されていない時はキューに追加する
|
||||||
|
!isPausingUpdate && // タブがバックグラウンドの時はキューに追加する
|
||||||
|
active.value // keepAliveで隠されている間はキューに追加する
|
||||||
|
) {
|
||||||
|
if (!items.value.has(item.id)) return; // 既にタイムラインにある場合は何もしない
|
||||||
|
unshiftItems([item]);
|
||||||
|
} else {
|
||||||
|
prependQueue(item);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新着アイテムをitemsの先頭に追加し、displayLimitを適用する
|
* 新着アイテムをitemsの先頭に追加し、limitを適用する
|
||||||
* @param newItems 新しいアイテムの配列
|
* @param newItems 新しいアイテムの配列
|
||||||
|
* @param limit デフォルトはdisplayLimit
|
||||||
*/
|
*/
|
||||||
function unshiftItems(newItems: MisskeyEntity[]) {
|
function unshiftItems(newItems: MisskeyEntity[], limit = displayLimit.value) {
|
||||||
const length = newItems.length + items.value.size;
|
const length = newItems.length + items.value.size;
|
||||||
items.value = new Map([...arrayToEntries(newItems), ...items.value].slice(0, props.displayLimit));
|
items.value = new Map([...arrayToEntries(newItems), ...items.value].slice(0, limit));
|
||||||
|
|
||||||
if (length >= props.displayLimit) more.value = true;
|
if (length >= displayLimit.value) more.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -394,18 +428,19 @@ function unshiftItems(newItems: MisskeyEntity[]) {
|
||||||
*/
|
*/
|
||||||
function concatItems(oldItems: MisskeyEntity[]) {
|
function concatItems(oldItems: MisskeyEntity[]) {
|
||||||
const length = oldItems.length + items.value.size;
|
const length = oldItems.length + items.value.size;
|
||||||
items.value = new Map([...items.value, ...arrayToEntries(oldItems)].slice(0, props.displayLimit));
|
items.value = new Map([...items.value, ...arrayToEntries(oldItems)].slice(0, displayLimit.value));
|
||||||
|
|
||||||
if (length >= props.displayLimit) more.value = true;
|
if (length >= displayLimit.value) more.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function executeQueue() {
|
function executeQueue() {
|
||||||
unshiftItems(Array.from(queue.value.values()));
|
const queueArr = Array.from(queue.value.entries());
|
||||||
queue.value = new Map();
|
unshiftItems(queueArr.slice(-1 * props.pagination.limit).map(v => v[1]));
|
||||||
|
queue.value = new Map(queueArr.slice(0, -1 * props.pagination.limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
function prependQueue(newItem: MisskeyEntity) {
|
function prependQueue(newItem: MisskeyEntity) {
|
||||||
queue.value = new Map([[newItem.id, newItem], ...queue.value].slice(0, props.displayLimit) as [string, MisskeyEntity][]);
|
queue.value = new Map([[newItem.id, newItem], ...queue.value] as [string, MisskeyEntity][]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -431,11 +466,11 @@ const updateItem = (id: MisskeyEntity['id'], replacer: (old: MisskeyEntity) => M
|
||||||
const inited = init();
|
const inited = init();
|
||||||
|
|
||||||
onActivated(() => {
|
onActivated(() => {
|
||||||
isBackTop.value = false;
|
// nothing to do
|
||||||
});
|
});
|
||||||
|
|
||||||
onDeactivated(() => {
|
onDeactivated(() => {
|
||||||
isBackTop.value = props.pagination.reversed ? window.scrollY >= (rootEl ? rootEl.scrollHeight - window.innerHeight : 0) : window.scrollY === 0;
|
// nothing to do
|
||||||
});
|
});
|
||||||
|
|
||||||
function toBottom() {
|
function toBottom() {
|
||||||
|
|
Loading…
Reference in a new issue