|
|
@@ -1122,6 +1122,8 @@ type HistoryRow =
|
|
|
interface HistorySectionProps {
|
|
|
items: PrintQueueItem[];
|
|
|
collapsed: boolean;
|
|
|
+ visibleCount: number;
|
|
|
+ onShowMore: () => void;
|
|
|
sortBy: 'date' | 'name' | 'printer';
|
|
|
sortAsc: boolean;
|
|
|
onSortByChange: (v: 'date' | 'name' | 'printer') => void;
|
|
|
@@ -1140,6 +1142,8 @@ interface HistorySectionProps {
|
|
|
|
|
|
function HistorySection({
|
|
|
items,
|
|
|
+ visibleCount,
|
|
|
+ onShowMore,
|
|
|
sortBy,
|
|
|
sortAsc,
|
|
|
onSortByChange,
|
|
|
@@ -1168,7 +1172,7 @@ function HistorySection({
|
|
|
// position from the parent's sort selector.
|
|
|
const rows: HistoryRow[] = [];
|
|
|
const seenBatches = new Set<number>();
|
|
|
- for (const item of items.slice(0, 50)) {
|
|
|
+ for (const item of items.slice(0, visibleCount)) {
|
|
|
if (item.batch_id != null) {
|
|
|
if (seenBatches.has(item.batch_id)) continue;
|
|
|
seenBatches.add(item.batch_id);
|
|
|
@@ -1316,10 +1320,25 @@ function HistorySection({
|
|
|
);
|
|
|
})}
|
|
|
</div>
|
|
|
+ {items.length > visibleCount && (
|
|
|
+ <div className="mt-4 flex flex-col items-center gap-2">
|
|
|
+ <Button variant="secondary" size="sm" onClick={onShowMore}>
|
|
|
+ {t('queue.history.showMore')}
|
|
|
+ </Button>
|
|
|
+ <span className="text-xs text-bambu-gray">
|
|
|
+ {t('queue.history.showingCount', {
|
|
|
+ shown: Math.min(visibleCount, items.length),
|
|
|
+ total: items.length,
|
|
|
+ })}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
</div>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+const HISTORY_PAGE_SIZE = 50;
|
|
|
+
|
|
|
export function QueuePage() {
|
|
|
const { t } = useTranslation();
|
|
|
const queryClient = useQueryClient();
|
|
|
@@ -1352,6 +1371,10 @@ export function QueuePage() {
|
|
|
const saved = localStorage.getItem('queue.historySortAsc');
|
|
|
return saved !== null ? saved === 'true' : false;
|
|
|
});
|
|
|
+ // #2682: History renders progressively — start at one page, grow on demand.
|
|
|
+ // Reset happens only on a deliberate re-sort / filter change (below), NOT on
|
|
|
+ // the periodic queue poll, so an expanded view doesn't snap back mid-scroll.
|
|
|
+ const [historyVisibleCount, setHistoryVisibleCount] = useState(HISTORY_PAGE_SIZE);
|
|
|
const [pendingSortBy, setPendingSortBy] = useState<'position' | 'name' | 'printer' | 'time'>(() => {
|
|
|
const saved = localStorage.getItem('queue.pendingSortBy');
|
|
|
return (saved as 'position' | 'name' | 'printer' | 'time') || 'position';
|
|
|
@@ -1409,6 +1432,13 @@ export function QueuePage() {
|
|
|
localStorage.setItem('queue.historySortAsc', String(historySortAsc));
|
|
|
}, [historySortAsc]);
|
|
|
|
|
|
+ // Collapse History back to a single page when the user re-sorts or changes
|
|
|
+ // the location filter (deliberate view changes). Intentionally excludes the
|
|
|
+ // queue poll so periodic refetches keep the expanded count.
|
|
|
+ useEffect(() => {
|
|
|
+ setHistoryVisibleCount(HISTORY_PAGE_SIZE);
|
|
|
+ }, [historySortBy, historySortAsc, filterLocation]);
|
|
|
+
|
|
|
useEffect(() => {
|
|
|
localStorage.setItem('queue.pendingSortBy', pendingSortBy);
|
|
|
}, [pendingSortBy]);
|
|
|
@@ -2334,6 +2364,8 @@ export function QueuePage() {
|
|
|
<HistorySection
|
|
|
items={historyItems}
|
|
|
collapsed={false}
|
|
|
+ visibleCount={historyVisibleCount}
|
|
|
+ onShowMore={() => setHistoryVisibleCount((c) => c + HISTORY_PAGE_SIZE)}
|
|
|
sortBy={historySortBy}
|
|
|
sortAsc={historySortAsc}
|
|
|
onSortByChange={setHistorySortBy}
|