From 524c46a554acc834ddc2ec0e99dac0d80c4f1460 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 1 Mar 2023 16:10:24 +0000 Subject: [PATCH] Fix multiple issues, clean up rendering, improve performance --- .../src/components/sheet/HeaderRow.svelte | 8 --- .../src/components/sheet/NewRow.svelte | 2 - .../src/components/sheet/ScrollOverlay.svelte | 35 ++++++++++--- .../src/components/sheet/Sheet.svelte | 2 - .../src/components/sheet/SheetCell.svelte | 13 ++--- .../src/components/sheet/SheetRow.svelte | 3 -- .../sheet/SheetScrollWrapper.svelte | 28 +++++++++-- .../src/components/sheet/stores/rows.js | 7 ++- .../src/components/sheet/stores/viewport.js | 49 +++++++------------ 9 files changed, 79 insertions(+), 68 deletions(-) diff --git a/packages/frontend-core/src/components/sheet/HeaderRow.svelte b/packages/frontend-core/src/components/sheet/HeaderRow.svelte index 71fd1237cc..01a50d07f2 100644 --- a/packages/frontend-core/src/components/sheet/HeaderRow.svelte +++ b/packages/frontend-core/src/components/sheet/HeaderRow.svelte @@ -38,13 +38,5 @@ diff --git a/packages/frontend-core/src/components/sheet/NewRow.svelte b/packages/frontend-core/src/components/sheet/NewRow.svelte index 764c207228..63985febf0 100644 --- a/packages/frontend-core/src/components/sheet/NewRow.svelte +++ b/packages/frontend-core/src/components/sheet/NewRow.svelte @@ -29,8 +29,6 @@ diff --git a/packages/frontend-core/src/components/sheet/stores/rows.js b/packages/frontend-core/src/components/sheet/stores/rows.js index 840798f1e2..0c4785ddba 100644 --- a/packages/frontend-core/src/components/sheet/stores/rows.js +++ b/packages/frontend-core/src/components/sheet/stores/rows.js @@ -4,7 +4,7 @@ import { fetchData } from "../../../fetch/fetchData" import { notifications } from "@budibase/bbui" export const createRowsStore = context => { - const { tableId, filter, API } = context + const { tableId, filter, API, scroll } = context // Flag for whether this is the first time loading our fetch let loaded = false @@ -61,12 +61,17 @@ export const createRowsStore = context => { loaded = true rowCacheMap = {} rows.set([]) + + // Enrich primary display into schema let newSchema = $$fetch.schema const primaryDisplay = $$fetch.definition?.primaryDisplay if (primaryDisplay && newSchema[primaryDisplay]) { newSchema[primaryDisplay].primaryDisplay = true } schema.set(newSchema) + + // Reset scroll state for fresh dataset + scroll.set({ left: 0, top: 0 }) } // Process new rows diff --git a/packages/frontend-core/src/components/sheet/stores/viewport.js b/packages/frontend-core/src/components/sheet/stores/viewport.js index 56987006a7..ef95965ff7 100644 --- a/packages/frontend-core/src/components/sheet/stores/viewport.js +++ b/packages/frontend-core/src/components/sheet/stores/viewport.js @@ -1,64 +1,53 @@ -import { writable, derived, get } from "svelte/store" +import { derived, get } from "svelte/store" export const createViewportStores = context => { const { cellHeight, columns, rows, scroll, bounds } = context - - // Use local variables to avoid needing to invoke 2 svelte getters each time - // scroll state changes, but also use stores to allow use of derived stores - let scrollTop = 0 - let scrollLeft = 0 - const scrollTopStore = writable(0) - const scrollLeftStore = writable(0) + const scrollTop = derived(scroll, $scroll => $scroll.top, 0) + const scrollLeft = derived(scroll, $scroll => $scroll.left, 0) // Derive height and width as primitives to avoid wasted computation const width = derived(bounds, $bounds => $bounds.width) const height = derived(bounds, $bounds => $bounds.height) - // Debounce scroll updates so we can slow down visible row computation - scroll.subscribe(({ left, top }) => { - scrollTop = top - scrollTopStore.set(top) - scrollLeft = left - scrollLeftStore.set(left) - }) - // Derive visible rows + // Split into multiple stores containing primitives to optimise invalidation + // as mich as possible + const firstRowIdx = derived(scrollTop, $scrollTop => { + return Math.floor($scrollTop / cellHeight) + }) + const visibleRowCount = derived(height, $height => { + return Math.ceil($height / cellHeight) + }) const visibleRows = derived( - [rows, scrollTopStore, height], - ([$rows, $scrollTop, $height]) => { - const maxRows = Math.ceil($height / cellHeight) + 1 - const firstRow = Math.max(0, Math.floor($scrollTop / cellHeight)) - return $rows.slice(firstRow, firstRow + maxRows) + [rows, firstRowIdx, visibleRowCount], + ([$rows, $firstRowIdx, $visibleRowCount]) => { + return $rows.slice($firstRowIdx, $firstRowIdx + $visibleRowCount) } ) // Derive visible columns const visibleColumns = derived( - [columns, scrollLeftStore, width], + [columns, scrollLeft, width], ([$columns, $scrollLeft, $width]) => { if (!$columns.length) { return [] } let startColIdx = 0 let rightEdge = $columns[0].width - while (rightEdge < $scrollLeft) { + while (rightEdge < $scrollLeft && startColIdx < $columns.length - 1) { startColIdx++ rightEdge += $columns[startColIdx].width } let endColIdx = startColIdx + 1 let leftEdge = rightEdge - while (leftEdge < $width + $scrollLeft) { - leftEdge += $columns[endColIdx]?.width + while (leftEdge < $width + $scrollLeft && endColIdx < $columns.length) { + leftEdge += $columns[endColIdx].width endColIdx++ } - return $columns.slice(Math.max(0, startColIdx - 1), endColIdx + 1) + return $columns.slice(startColIdx, endColIdx) } ) - // visibleColumns.subscribe(state => { - // console.log(state) - // }) - // Fetch next page when approaching end of data visibleRows.subscribe($visibleRows => { const lastVisible = $visibleRows[$visibleRows.length - 1]