From 47f9c70583a9d0d2ec195a1ffc10591caf68636d Mon Sep 17 00:00:00 2001 From: 3ll3d00d Date: Mon, 11 Sep 2023 08:24:36 +0100 Subject: [PATCH] make UI more responsive to catalogue loads --- ezbeq/catalogue.py | 13 +++-- ezbeq/config.py | 6 +- pyproject.toml | 2 +- ui/src/App.jsx | 84 +++++++++++++--------------- ui/src/components/main/Catalogue.jsx | 72 +++++++++++------------- 5 files changed, 88 insertions(+), 89 deletions(-) diff --git a/ezbeq/catalogue.py b/ezbeq/catalogue.py index 86d99ac..ed979f4 100644 --- a/ezbeq/catalogue.py +++ b/ezbeq/catalogue.py @@ -277,13 +277,13 @@ def meta_msg(self) -> str: class Catalogues: - def __init__(self, config_path: str, catalogue_url: str, ws: WsServer, refresh_seconds: float, chunk_size: int, - sync_load: bool): + def __init__(self, config_path: str, catalogue_url: str, ws: WsServer, refresh_seconds: float, + first_chunk_size: int, chunk_size: int, sync_load: bool): self.__catalogue_url = catalogue_url self.__version_file = os.path.join(config_path, 'version.txt') self.__catalogue_file = os.path.join(config_path, 'database.json') self.__db = os.path.join(config_path, 'ezbeq.db') - self.__chunk_size = chunk_size + self.__chunk_sizes = (first_chunk_size, chunk_size) logger.info(f'Using database at {self.__db}') self.__ensure_db() self.__refresh_interval = refresh_seconds @@ -305,7 +305,7 @@ def __send_chunked_catalogue(self, sender: Callable[[str], None]): catalogue = self.latest if not catalogue: return - vals = {'count': catalogue.count, 'limit': 250, 'offset': 0, 'start': time.time()} + vals = {'count': catalogue.count, 'limit': self.__chunk_sizes[0], 'offset': 0, 'start': time.time()} from twisted.internet import threads threads.deferToThread(lambda: self.__load_next_chunk(sender, catalogue.version, **vals)).addCallback(sender) @@ -314,6 +314,8 @@ def __load_next_chunk(self, publisher: Callable[[str], None], version: str, coun if offset >= count: logger.info(f'Load complete for {version} in {to_millis(start, time.time())}ms') else: + if offset == 0: + time.sleep(1) begin = time.time() next_offset = offset + limit select = f"SELECT {UI_FIELDS_STR} FROM catalogue_entry WHERE version = '{version}'" @@ -323,7 +325,7 @@ def __load_next_chunk(self, publisher: Callable[[str], None], version: str, coun }, ensure_ascii=False) end = time.time() logger.info(f'Loaded chunk from {offset} to {next_offset} in {to_millis(begin, end)}ms') - vals = {'count': count, 'limit': self.__chunk_size, 'offset': next_offset, 'start': start} + vals = {'count': count, 'limit': self.__chunk_sizes[1], 'offset': next_offset, 'start': start} from twisted.internet import threads threads.deferToThread(lambda: self.__load_next_chunk(publisher, version, **vals)).addCallback(publisher) return msg @@ -649,6 +651,7 @@ def __init__(self, config: Config, ws: WsServer): config.beqcatalogue_url, ws, config.catalogue_refresh_interval, + config.first_chunk_size, config.chunk_size, config.load_catalogue_at_startup) diff --git a/ezbeq/config.py b/ezbeq/config.py index 8781905..5f22795 100644 --- a/ezbeq/config.py +++ b/ezbeq/config.py @@ -38,7 +38,11 @@ def enable_metrics(self) -> bool: @property def chunk_size(self) -> int: - return self.config.get('chunk_size', 4000) + return max(self.config.get('chunk_size', 4000), 1) + + @property + def first_chunk_size(self) -> int: + return max(self.config.get('first_chunk_size', self.chunk_size), 1) @property def beqcatalogue_url(self) -> str: diff --git a/pyproject.toml b/pyproject.toml index 3a63b32..45cdaa3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "ezbeq" -version = "2.0.0a8" +version = "2.0.0a9" description = "A webapp which can send beqcatalogue filters to a DSP device" authors = ["3ll3d00d "] license = "MIT" diff --git a/ui/src/App.jsx b/ui/src/App.jsx index 3091336..839c938 100644 --- a/ui/src/App.jsx +++ b/ui/src/App.jsx @@ -114,53 +114,49 @@ const App = () => { { - Object.keys(entries).length > 0 - ? - selectedNav === 'catalogue' + selectedNav === 'catalogue' + ? + entries[e])} + setErr={setErr} + replaceDevice={d => { + if (ss && ss.isConnected()) { + console.debug(`Discarding update, ws is connected`); + } else { + console.debug(`Accepting update, ws is disconnected`); + replaceDevice(d); + } + }} + availableDevices={availableDevices} + selectedDeviceName={selectedDeviceName} + setSelectedDeviceName={setSelectedDeviceName} + selectedSlotId={selectedSlotId} + setSelectedSlotId={setSelectedSlotId} + useWide={useWide} + selectedNav={selectedNav} + setSelectedNav={setSelectedNav} + meta={meta} + /> + : + selectedNav === 'levels' ? - entries[e])} - setErr={setErr} - replaceDevice={d => { - if (ss && ss.isConnected()) { - console.debug(`Discarding update, ws is connected`); - } else { - console.debug(`Accepting update, ws is disconnected`); - replaceDevice(d); - } - }} - availableDevices={availableDevices} - selectedDeviceName={selectedDeviceName} - setSelectedDeviceName={setSelectedDeviceName} - selectedSlotId={selectedSlotId} - setSelectedSlotId={setSelectedSlotId} - useWide={useWide} - selectedNav={selectedNav} - setSelectedNav={setSelectedNav} - meta={meta} + : - selectedNav === 'levels' - ? - - : - - : - null + } diff --git a/ui/src/components/main/Catalogue.jsx b/ui/src/components/main/Catalogue.jsx index b41edad..a10d411 100644 --- a/ui/src/components/main/Catalogue.jsx +++ b/ui/src/components/main/Catalogue.jsx @@ -84,44 +84,40 @@ const Catalogue = ({entries, setSelectedEntryId, selectedEntryId, useWide, selec sortable: false } ]; - if (entries.length > 0) { - const topNav = 64; - const gain = 56; - const deviceRowHeight = 75; - const deviceRows = selectedDevice && selectedDevice.slots ? Math.ceil(selectedDevice.slots.length / 2) : 0; - const gainHeight = selectedDevice ? (['minidsp', 'camilladsp'].indexOf(selectedDevice.type) === -1 ? 0 : gain) : 0; - const upperNavHeight = topNav + gainHeight + (deviceRows * deviceRowHeight); - const bottomNavHeight = 24; - // portrait mode so reduce space allocated to the grid - const halfHeight = selectedEntryId !== -1 && !useWide; - const gridHeight = Math.max(260, (window.innerHeight - upperNavHeight - bottomNavHeight) / (halfHeight ? 2 : 1)); - // console.debug(`showBottom: ${hasMultipleTabs} / ${selectedEntryId} / ${useWide} / ${deviceRows} * ${deviceRowHeight} / ${halfHeight}`); - // console.debug(`numerator: ${window.innerHeight} - ${upperNavHeight} - ${bottomNavHeight} = ${window.innerHeight - upperNavHeight - bottomNavHeight}`); - // console.debug(`denominator: ${halfHeight ? 2 : 1}`); - // console.debug(`Grid Height: ${gridHeight}`); - const authors = new Set(entries.map(e => e.author)); - const grid = - - setSelectedEntryId(e[0])} - columnVisibilityModel={{sortTitle: false, edition: useWide, author: authors.size > 1}} - sx={{p: 0, '& .avatar': { paddingLeft: '0px', paddingRight: '0px' }}} - disableColumnMenu={true} - getCellClassName={(params) => params.field === 'author' ? 'avatar' : ''} - hideFooterSelectedRowCount={true} - /> - ; - return useWide ? grid : {grid}; - } else { - return null; - } + const topNav = 64; + const gain = 56; + const deviceRowHeight = 75; + const deviceRows = selectedDevice && selectedDevice.slots ? Math.ceil(selectedDevice.slots.length / 2) : 0; + const gainHeight = selectedDevice ? (['minidsp', 'camilladsp'].indexOf(selectedDevice.type) === -1 ? 0 : gain) : 0; + const upperNavHeight = topNav + gainHeight + (deviceRows * deviceRowHeight); + const bottomNavHeight = 24; + // portrait mode so reduce space allocated to the grid + const halfHeight = selectedEntryId !== -1 && !useWide; + const gridHeight = Math.max(260, (window.innerHeight - upperNavHeight - bottomNavHeight) / (halfHeight ? 2 : 1)); + // console.debug(`showBottom: ${hasMultipleTabs} / ${selectedEntryId} / ${useWide} / ${deviceRows} * ${deviceRowHeight} / ${halfHeight}`); + // console.debug(`numerator: ${window.innerHeight} - ${upperNavHeight} - ${bottomNavHeight} = ${window.innerHeight - upperNavHeight - bottomNavHeight}`); + // console.debug(`denominator: ${halfHeight ? 2 : 1}`); + // console.debug(`Grid Height: ${gridHeight}`); + const authors = new Set(entries.map(e => e.author)); + const grid = + + setSelectedEntryId(e[0])} + columnVisibilityModel={{sortTitle: false, edition: useWide, author: authors.size > 1}} + sx={{p: 0, '& .avatar': { paddingLeft: '0px', paddingRight: '0px' }}} + disableColumnMenu={true} + getCellClassName={(params) => params.field === 'author' ? 'avatar' : ''} + hideFooterSelectedRowCount={true} + /> + ; + return useWide ? grid : {grid}; }; export default Catalogue; \ No newline at end of file