Skip to content

Commit

Permalink
make UI more responsive to catalogue loads
Browse files Browse the repository at this point in the history
  • Loading branch information
3ll3d00d committed Sep 11, 2023
1 parent ae797ab commit 47f9c70
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 89 deletions.
13 changes: 8 additions & 5 deletions ezbeq/catalogue.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)

Expand All @@ -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}'"
Expand All @@ -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
Expand Down Expand Up @@ -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)

Expand Down
6 changes: 5 additions & 1 deletion ezbeq/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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 <mattkhan+ezbeq@gmail.com>"]
license = "MIT"
Expand Down
84 changes: 40 additions & 44 deletions ui/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,53 +114,49 @@ const App = () => {
<Root>
<ErrorSnack err={err} setErr={setErr}/>
{
Object.keys(entries).length > 0
?
selectedNav === 'catalogue'
selectedNav === 'catalogue'
?
<MainView entries={Object.keys(entries).map(e => 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'
?
<MainView entries={Object.keys(entries).map(e => 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}
<Levels availableDevices={availableDevices}
selectedDeviceName={selectedDeviceName}
setSelectedDeviceName={setSelectedDeviceName}
levelsService={levelsService}
selectedNav={selectedNav}
setSelectedNav={setSelectedNav}
theme={theme}
/>
:
selectedNav === 'levels'
?
<Levels availableDevices={availableDevices}
selectedDeviceName={selectedDeviceName}
setSelectedDeviceName={setSelectedDeviceName}
levelsService={levelsService}
selectedNav={selectedNav}
setSelectedNav={setSelectedNav}
theme={theme}
/>
:
<Minidsp availableDevices={availableDevices}
selectedDeviceName={selectedDeviceName}
setSelectedDeviceName={setSelectedDeviceName}
selectedSlotId={selectedSlotId}
setErr={setErr}
selectedNav={selectedNav}
setSelectedNav={setSelectedNav}
theme={theme}
/>
:
null
<Minidsp availableDevices={availableDevices}
selectedDeviceName={selectedDeviceName}
setSelectedDeviceName={setSelectedDeviceName}
selectedSlotId={selectedSlotId}
setErr={setErr}
selectedNav={selectedNav}
setSelectedNav={setSelectedNav}
theme={theme}
/>
}
</Root>
</ThemeProvider>
Expand Down
72 changes: 34 additions & 38 deletions ui/src/components/main/Catalogue.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
<Grid item style={{
height: `${gridHeight}px`,
width: '100%'
}}>
<UnpaddedDataGrid rows={entries}
columns={catalogueGridColumns}
pageSize={50}
density={'compact'}
initialState={{sorting: {sortModel: [{field: 'sortTitle', sort: 'asc'}]}}}
onRowSelectionModelChange={e => 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}
/>
</Grid>;
return useWide ? grid : <Grid container sx={{ml: 0}}>{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 =
<Grid item style={{
height: `${gridHeight}px`,
width: '100%'
}}>
<UnpaddedDataGrid rows={entries}
columns={catalogueGridColumns}
pageSize={50}
density={'compact'}
initialState={{sorting: {sortModel: [{field: 'sortTitle', sort: 'asc'}]}}}
onRowSelectionModelChange={e => 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}
/>
</Grid>;
return useWide ? grid : <Grid container sx={{ml: 0}}>{grid}</Grid>;
};

export default Catalogue;

0 comments on commit 47f9c70

Please sign in to comment.