This commit is contained in:
syuilo 2025-05-02 09:37:51 +09:00
parent 287380b2db
commit 295fe859d8
2 changed files with 55 additions and 24 deletions

View File

@ -19,12 +19,10 @@ SPDX-License-Identifier: AGPL-3.0-only
</div> </div>
<div v-else ref="rootEl"> <div v-else ref="rootEl">
<div v-if="paginator.queue.value.length > 0" :class="$style.new" @click="releaseQueue()"> <div v-if="paginator.queuedAheadItemsCount.value > 0" :class="$style.new">
<div :class="$style.newBg1"></div> <div :class="$style.newBg1"></div>
<div :class="$style.newBg2"></div> <div :class="$style.newBg2"></div>
<div :class="$style.newBg3"></div> <button class="_button" :class="$style.newButton" @click="releaseQueue()"><i class="ti ti-circle-arrow-up"></i> {{ i18n.ts.newNote }}</button>
<div :class="$style.newBg4"></div>
<button class="_button" :class="$style.newButton"><i class="ti ti-circle-arrow-up"></i> {{ i18n.ts.newNote }}</button>
</div> </div>
<component <component
:is="prefer.s.animation ? TransitionGroup : 'div'" :is="prefer.s.animation ? TransitionGroup : 'div'"
@ -405,26 +403,46 @@ defineExpose({
} }
/* 疑似progressive blur */ /* 疑似progressive blur */
.newBg1, .newBg2, .newBg3, .newBg4 { .newBg1, .newBg2 {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
-webkit-backdrop-filter: var(--MI-blur, blur(1px)); }
backdrop-filter: var(--MI-blur, blur(1px));
.newBg1 {
height: 100%;
-webkit-backdrop-filter: var(--MI-blur, blur(2px));
backdrop-filter: var(--MI-blur, blur(2px));
mask-image: linear-gradient( /* 疑似Easing Linear Gradients */
to top,
rgb(0 0 0 / 0%) 0%,
rgb(0 0 0 / 4.9%) 7.75%,
rgb(0 0 0 / 10.4%) 11.25%,
rgb(0 0 0 / 45%) 23.55%,
rgb(0 0 0 / 55%) 26.45%,
rgb(0 0 0 / 89.6%) 38.75%,
rgb(0 0 0 / 95.1%) 42.25%,
rgb(0 0 0 / 100%) 50%
);
} }
.newBg2 { .newBg2 {
height: 75%; height: 75%;
} -webkit-backdrop-filter: var(--MI-blur, blur(4px));
backdrop-filter: var(--MI-blur, blur(4px));
.newBg3 { mask-image: linear-gradient( /* 疑似Easing Linear Gradients */
height: 50%; to top,
} rgb(0 0 0 / 0%) 0%,
rgb(0 0 0 / 4.9%) 15.5%,
.newBg4 { rgb(0 0 0 / 10.4%) 22.5%,
height: 25%; rgb(0 0 0 / 45%) 47.1%,
rgb(0 0 0 / 55%) 52.9%,
rgb(0 0 0 / 89.6%) 77.5%,
rgb(0 0 0 / 95.1%) 91.9%,
rgb(0 0 0 / 100%) 100%
);
} }
.newButton { .newButton {

View File

@ -9,6 +9,7 @@ import type { ComputedRef, Ref, ShallowRef } from 'vue';
import { misskeyApi } from '@/utility/misskey-api.js'; import { misskeyApi } from '@/utility/misskey-api.js';
const MAX_ITEMS = 20; const MAX_ITEMS = 20;
const MAX_QUEUE_ITEMS = 100;
const FIRST_FETCH_LIMIT = 15; const FIRST_FETCH_LIMIT = 15;
const SECOND_FETCH_LIMIT = 30; const SECOND_FETCH_LIMIT = 30;
@ -43,7 +44,8 @@ export function usePagination<T extends MisskeyEntity>(props: {
useShallowRef?: boolean; useShallowRef?: boolean;
}) { }) {
const items = props.useShallowRef ? shallowRef<T[]>([]) : ref<T[]>([]); const items = props.useShallowRef ? shallowRef<T[]>([]) : ref<T[]>([]);
const queue = props.useShallowRef ? shallowRef<T[]>([]) : ref<T[]>([]); let aheadQueue: T[] = [];
const queuedAheadItemsCount = ref(0);
const fetching = ref(true); const fetching = ref(true);
const moreFetching = ref(false); const moreFetching = ref(false);
const canFetchMore = ref(false); const canFetchMore = ref(false);
@ -54,6 +56,9 @@ export function usePagination<T extends MisskeyEntity>(props: {
function getNewestId() { function getNewestId() {
// 様々な要因により並び順は保証されないのでソートが必要 // 様々な要因により並び順は保証されないのでソートが必要
if (aheadQueue.length > 0) {
return aheadQueue.map(x => x.id).sort().at(-1);
}
return items.value.map(x => x.id).sort().at(-1); return items.value.map(x => x.id).sort().at(-1);
} }
@ -64,7 +69,8 @@ export function usePagination<T extends MisskeyEntity>(props: {
async function init(): Promise<void> { async function init(): Promise<void> {
items.value = []; items.value = [];
queue.value = []; aheadQueue = [];
queuedAheadItemsCount.value = 0;
fetching.value = true; fetching.value = true;
const params = props.ctx.params ? isRef(props.ctx.params) ? props.ctx.params.value : props.ctx.params : {}; const params = props.ctx.params ? isRef(props.ctx.params) ? props.ctx.params.value : props.ctx.params : {};
await misskeyApi<T[]>(props.ctx.endpoint, { await misskeyApi<T[]>(props.ctx.endpoint, {
@ -143,8 +149,11 @@ export function usePagination<T extends MisskeyEntity>(props: {
}), }),
}).then(res => { }).then(res => {
if (options.toQueue) { if (options.toQueue) {
queue.value.unshift(...res.toReversed()); aheadQueue.unshift(...res.toReversed());
if (props.useShallowRef) triggerRef(queue); if (aheadQueue.length > MAX_QUEUE_ITEMS) {
aheadQueue = aheadQueue.slice(0, MAX_QUEUE_ITEMS);
}
queuedAheadItemsCount.value = aheadQueue.length;
} else { } else {
items.value.unshift(...res.toReversed()); items.value.unshift(...res.toReversed());
if (props.useShallowRef) triggerRef(items); if (props.useShallowRef) triggerRef(items);
@ -173,13 +182,17 @@ export function usePagination<T extends MisskeyEntity>(props: {
} }
function enqueue(item: T) { function enqueue(item: T) {
queue.value.unshift(item); aheadQueue.unshift(item);
if (props.useShallowRef) triggerRef(queue); if (aheadQueue.length > MAX_QUEUE_ITEMS) {
aheadQueue.pop();
}
queuedAheadItemsCount.value = aheadQueue.length;
} }
function releaseQueue() { function releaseQueue() {
unshiftItems(queue.value); unshiftItems(aheadQueue);
queue.value = []; aheadQueue = [];
queuedAheadItemsCount.value = 0;
} }
onMounted(() => { onMounted(() => {
@ -188,7 +201,7 @@ export function usePagination<T extends MisskeyEntity>(props: {
return { return {
items, items,
queue, queuedAheadItemsCount,
fetching, fetching,
moreFetching, moreFetching,
canFetchMore, canFetchMore,