diff --git a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx index 88b4100e4..e8059e967 100644 --- a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +++ b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx @@ -13,7 +13,7 @@ import { Alert, Avatar, Tooltip, useTheme } from '@mui/material' import { observer } from 'mobx-react' import React, { useEffect, useState } from 'react' import { makeStyles } from 'tss-react/mui' - +import { CheckResultI } from '@apollo-annotation/mst' import { LinearApolloDisplay as LinearApolloDisplayI } from '../stateModel' interface LinearApolloDisplayProps { @@ -50,7 +50,6 @@ export const LinearApolloDisplay = observer(function LinearApolloDisplay( apolloRowHeight, contextMenuItems: getContextMenuItems, cursor, - featuresHeight, isShown, onMouseDown, onMouseLeave, @@ -68,16 +67,92 @@ export const LinearApolloDisplay = observer(function LinearApolloDisplay( const { classes } = useStyles() const lgv = getContainingView(model) as unknown as LinearGenomeViewModel + const [featuresHeight, setFeatureHeight] = useState() + useEffect(() => { + function getFeaturesHeight() { + const featuresHeight = model.getFeaturesHeight() + setFeatureHeight(featuresHeight) + } + getFeaturesHeight() + }) + useEffect(() => { setTheme(theme) }, [theme, setTheme]) + + const { assemblyManager } = session as unknown as AbstractSessionModel + + const [checkInfo, setCheckInfo] = useState< + ({ + checkResult: CheckResultI + top: number + left: number + height: number + } | null)[] + >([]) + + useEffect(() => { + async function getCheckInfo() { + const info = await Promise.all( + lgv.displayedRegions.flatMap((region, idx) => { + const assembly = assemblyManager.get(region.assemblyName) + return [...session.apolloDataStore.checkResults.values()] + .filter( + (checkResult) => + assembly?.isValidRefName(checkResult.refSeq) && + assembly.getCanonicalRefName(checkResult.refSeq) === + region.refName && + doesIntersect2( + region.start, + region.end, + checkResult.start, + checkResult.end, + ), + ) + .map(async (checkResult) => { + const left = + (lgv.bpToPx({ + refName: region.refName, + coord: checkResult.start, + regionNumber: idx, + })?.offsetPx ?? 0) - lgv.offsetPx + const [feature] = checkResult.ids + if (!feature) { + return null + } + const { topLevelFeature } = feature + + let row = 0 + if (parent) { + const pos = + await model.getFeatureLayoutPosition(topLevelFeature) + if (pos?.layoutRow) { + row = pos.layoutRow + } + } + const top = row * apolloRowHeight + const height = apolloRowHeight + return { checkResult, top, left, height } + }) + }), + ) + setCheckInfo(info) + } + void getCheckInfo() + }, [ + apolloRowHeight, + assemblyManager, + lgv, + model, + session.apolloDataStore.checkResults, + ]) + const [contextCoord, setContextCoord] = useState() const [contextMenuItems, setContextMenuItems] = useState([]) const message = regionCannotBeRendered() if (!isShown) { return null } - const { assemblyManager } = session as unknown as AbstractSessionModel return ( <> {lgv.bpPerPx <= 3 ? ( @@ -173,50 +248,21 @@ export const LinearApolloDisplay = observer(function LinearApolloDisplay( style={{ cursor: cursor ?? 'default' }} data-testid="overlayCanvas" /> - {lgv.displayedRegions.flatMap((region, idx) => { - const assembly = assemblyManager.get(region.assemblyName) - return [...session.apolloDataStore.checkResults.values()] - .filter( - (checkResult) => - assembly?.isValidRefName(checkResult.refSeq) && - assembly.getCanonicalRefName(checkResult.refSeq) === - region.refName && - doesIntersect2( - region.start, - region.end, - checkResult.start, - checkResult.end, - ), - ) - .map((checkResult) => { - const left = - (lgv.bpToPx({ - refName: region.refName, - coord: checkResult.start, - regionNumber: idx, - })?.offsetPx ?? 0) - lgv.offsetPx - const [feature] = checkResult.ids - if (!feature) { - return null - } - const { topLevelFeature } = feature - const row = parent - ? model.getFeatureLayoutPosition(topLevelFeature) - ?.layoutRow ?? 0 - : 0 - const top = row * apolloRowHeight - const height = apolloRowHeight - return ( - - - - - - ) - }) + {checkInfo.map((info) => { + if (!info) { + return null + } + const { checkResult, height, left, top } = info + return ( + + + + + + ) })} 0} diff --git a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/BoxGlyph.ts b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/BoxGlyph.ts index 5ddd8bafc..e7093d0f2 100644 --- a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +++ b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/BoxGlyph.ts @@ -62,7 +62,8 @@ function drawBoxText( ctx.fillText(text, textStart, y + 11, textWidth) } -function draw( +// eslint-disable-next-line @typescript-eslint/require-await +async function draw( ctx: CanvasRenderingContext2D, feature: AnnotationFeature, row: number, @@ -132,7 +133,7 @@ function drawDragPreview( overlayCtx.fillRect(rectX, rectY, rectWidth, rectHeight) } -function drawHover( +async function drawHover( stateModel: LinearApolloDisplay, ctx: CanvasRenderingContext2D, ) { @@ -141,7 +142,7 @@ function drawHover( return } const { feature } = apolloHover - const position = stateModel.getFeatureLayoutPosition(feature) + const position = await stateModel.getFeatureLayoutPosition(feature) if (!position) { return } @@ -162,16 +163,16 @@ function drawHover( ctx.fillRect(startPx, top, widthPx, apolloRowHeight) } -function drawTooltip( +async function drawTooltip( display: LinearApolloDisplayMouseEvents, context: CanvasRenderingContext2D, -): void { +): Promise { const { apolloHover, apolloRowHeight, lgv, theme } = display if (!apolloHover) { return } const { feature } = apolloHover - const position = display.getFeatureLayoutPosition(feature) + const position = await display.getFeatureLayoutPosition(feature) if (!position) { return } @@ -388,11 +389,12 @@ function getContextMenuItems( return menuItems } -function getFeatureFromLayout( +// eslint-disable-next-line @typescript-eslint/require-await +async function getFeatureFromLayout( feature: AnnotationFeature, _bp: number, _row: number, -): AnnotationFeature { +): Promise { return feature } @@ -400,10 +402,11 @@ function getRowCount(_feature: AnnotationFeature) { return 1 } -function getRowForFeature( +// eslint-disable-next-line @typescript-eslint/require-await +async function getRowForFeature( _feature: AnnotationFeature, _childFeature: AnnotationFeature, -): number | undefined { +): Promise { return 0 } diff --git a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/GeneGlyph.ts b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/GeneGlyph.ts index 32ed3777f..98d9dd9e1 100644 --- a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +++ b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/GeneGlyph.ts @@ -12,6 +12,7 @@ import { CanvasMouseEvent } from '../types' import { Glyph } from './Glyph' import { boxGlyph } from './BoxGlyph' import { LinearApolloDisplayRendering } from '../stateModel/rendering' +import { OntologyManager } from '../../OntologyManager' let forwardFill: CanvasPattern | null = null let backwardFill: CanvasPattern | null = null @@ -47,14 +48,15 @@ if ('document' in window) { } } -function draw( +async function draw( ctx: CanvasRenderingContext2D, feature: AnnotationFeature, row: number, stateModel: LinearApolloDisplayRendering, displayedRegionIndex: number, -): void { +): Promise { const { apolloRowHeight, lgv, session, theme } = stateModel + const { apolloDataStore } = session const { bpPerPx, displayedRegions, offsetPx } = lgv const displayedRegion = displayedRegions[displayedRegionIndex] const { refName, reversed } = displayedRegion @@ -71,7 +73,11 @@ function draw( // Draw lines on different rows for each mRNA let currentRow = 0 for (const [, mrna] of children) { - if (mrna.type !== 'mRNA') { + const isMrna = await apolloDataStore.ontologyManager.isTypeOf( + mrna.type, + 'mRNA', + ) + if (!isMrna) { currentRow += 1 continue } @@ -106,7 +112,7 @@ function draw( currentRow = 0 for (const [, child] of children) { if (child.type !== 'mRNA') { - boxGlyph.draw(ctx, child, row, stateModel, displayedRegionIndex) + await boxGlyph.draw(ctx, child, row, stateModel, displayedRegionIndex) currentRow += 1 continue } @@ -253,7 +259,7 @@ function drawDragPreview( overlayCtx.fillRect(rectX, rectY, rectWidth, rectHeight) } -function drawHover( +async function drawHover( stateModel: LinearApolloDisplay, ctx: CanvasRenderingContext2D, ) { @@ -262,7 +268,7 @@ function drawHover( return } const { feature } = apolloHover - const position = stateModel.getFeatureLayoutPosition(feature) + const position = await stateModel.getFeatureLayoutPosition(feature) if (!position) { return } @@ -284,12 +290,14 @@ function drawHover( ctx.fillRect(startPx, top, widthPx, apolloRowHeight * getRowCount(feature)) } -function getFeatureFromLayout( +async function getFeatureFromLayout( feature: AnnotationFeature, bp: number, row: number, -): AnnotationFeature | undefined { - const featureInThisRow: AnnotationFeature[] = featuresForRow(feature)[row] + ontologyManager: OntologyManager, +): Promise { + const ff = await featuresForRow(feature, ontologyManager) + const featureInThisRow: AnnotationFeature[] = ff[row] for (const f of featureInThisRow) { if (bp >= f.min && bp <= f.max && f.parent) { return f @@ -324,8 +332,12 @@ function getRowCount(feature: AnnotationFeature, _bpPerPx?: number): number { * If the row contains an mRNA, the order is CDS -\> exon -\> mRNA -\> gene * If the row does not contain an mRNA, the order is subfeature -\> gene */ -function featuresForRow(feature: AnnotationFeature): AnnotationFeature[][] { - if (feature.type !== 'gene') { +async function featuresForRow( + feature: AnnotationFeature, + ontologyManager: OntologyManager, +): Promise { + const isGene = await ontologyManager.isTypeOf(feature.type, 'gene') + if (!isGene) { throw new Error('Top level feature for GeneGlyph must have type "gene"') } const { children } = feature @@ -357,11 +369,12 @@ function featuresForRow(feature: AnnotationFeature): AnnotationFeature[][] { return features } -function getRowForFeature( +async function getRowForFeature( feature: AnnotationFeature, childFeature: AnnotationFeature, + ontologyManager: OntologyManager, ) { - const rows = featuresForRow(feature) + const rows = await featuresForRow(feature, ontologyManager) for (const [idx, row] of rows.entries()) { if (row.some((feature) => feature._id === childFeature._id)) { return idx diff --git a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts index ebbeeaeab..179e2ea9b 100644 --- a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +++ b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts @@ -19,7 +19,7 @@ function getRowCount(feature: AnnotationFeature) { return featuresForRow(feature).length } -function draw( +async function draw( ctx: CanvasRenderingContext2D, feature: AnnotationFeature, row: number, @@ -27,11 +27,11 @@ function draw( displayedRegionIndex: number, ) { for (let i = 0; i < getRowCount(feature); i++) { - drawRow(ctx, feature, row + i, row, stateModel, displayedRegionIndex) + await drawRow(ctx, feature, row + i, row, stateModel, displayedRegionIndex) } } -function drawRow( +async function drawRow( ctx: CanvasRenderingContext2D, topLevelFeature: AnnotationFeature, row: number, @@ -41,11 +41,11 @@ function drawRow( ) { const features = featuresForRow(topLevelFeature)[row - topRow] for (const feature of features) { - drawFeature(ctx, feature, row, stateModel, displayedRegionIndex) + await drawFeature(ctx, feature, row, stateModel, displayedRegionIndex) } } -function drawFeature( +async function drawFeature( ctx: CanvasRenderingContext2D, feature: AnnotationFeature, row: number, @@ -74,10 +74,10 @@ function drawFeature( const featureHeight = rowCount * heightPx drawBox(ctx, startPx, top, widthPx, featureHeight, groupingColor) } - boxGlyph.draw(ctx, feature, row, stateModel, displayedRegionIndex) + await boxGlyph.draw(ctx, feature, row, stateModel, displayedRegionIndex) } -function drawHover( +async function drawHover( stateModel: LinearApolloDisplay, ctx: CanvasRenderingContext2D, ) { @@ -86,7 +86,7 @@ function drawHover( return } const { feature } = apolloHover - const position = stateModel.getFeatureLayoutPosition(feature) + const position = await stateModel.getFeatureLayoutPosition(feature) if (!position) { return } @@ -107,7 +107,8 @@ function drawHover( ctx.fillRect(startPx, top, widthPx, apolloRowHeight * getRowCount(feature)) } -function getFeatureFromLayout( +// eslint-disable-next-line @typescript-eslint/require-await +async function getFeatureFromLayout( feature: AnnotationFeature, bp: number, row: number, @@ -116,7 +117,8 @@ function getFeatureFromLayout( return layoutRow.find((f) => bp >= f.min && bp <= f.max) } -function getRowForFeature( +// eslint-disable-next-line @typescript-eslint/require-await +async function getRowForFeature( feature: AnnotationFeature, childFeature: AnnotationFeature, ) { diff --git a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/Glyph.ts b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/Glyph.ts index d360518de..85e259152 100644 --- a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/Glyph.ts +++ b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/Glyph.ts @@ -7,6 +7,7 @@ import { } from '../stateModel/mouseEvents' import { LinearApolloDisplayRendering } from '../stateModel/rendering' import { CanvasMouseEvent } from '../types' +import { OntologyManager } from '../../OntologyManager' export interface Glyph { /** @returns number of layout rows used by this glyph with this feature and zoom level */ @@ -18,22 +19,24 @@ export interface Glyph { row: number, stateModel: LinearApolloDisplayRendering, displayedRegionIndex: number, - ): void + ): Promise /** @returns the feature or subfeature at the given bp and row number in this glyph's layout */ getFeatureFromLayout( feature: AnnotationFeature, bp: number, row: number, - ): AnnotationFeature | undefined + ontologyManager: OntologyManager, + ): Promise getRowForFeature( feature: AnnotationFeature, childFeature: AnnotationFeature, - ): number | undefined + ontologyManager: OntologyManager, + ): Promise drawHover( display: LinearApolloDisplayMouseEvents, overlayCtx: CanvasRenderingContext2D, - ): void + ): Promise drawDragPreview( display: LinearApolloDisplayMouseEvents, @@ -67,7 +70,7 @@ export interface Glyph { drawTooltip( display: LinearApolloDisplayMouseEvents, context: CanvasRenderingContext2D, - ): void + ): Promise getContextMenuItems(display: LinearApolloDisplayMouseEvents): MenuItem[] } diff --git a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/stateModel/layouts.ts b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/stateModel/layouts.ts index 4e1943a76..8b2078b6d 100644 --- a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/stateModel/layouts.ts +++ b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/stateModel/layouts.ts @@ -156,7 +156,7 @@ export function layoutsModelFactory( return featureLayout }) }, - getFeatureLayoutPosition(feature: AnnotationFeature) { + async getFeatureLayoutPosition(feature: AnnotationFeature) { const { featureLayouts } = this for (const [idx, layout] of featureLayouts.entries()) { for (const [layoutRowNum, layoutRow] of layout) { @@ -174,9 +174,10 @@ export function layoutsModelFactory( } } if (layoutFeature.hasDescendant(feature._id)) { - const row = getGlyph(layoutFeature).getRowForFeature( + const row = await getGlyph(layoutFeature).getRowForFeature( layoutFeature, feature, + self.session.apolloDataStore.ontologyManager, ) if (row !== undefined) { return { diff --git a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/stateModel/mouseEvents.ts b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/stateModel/mouseEvents.ts index 34b649e0c..ab1469773 100644 --- a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/stateModel/mouseEvents.ts +++ b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/stateModel/mouseEvents.ts @@ -131,7 +131,7 @@ export function mouseEventsModelIntermediateFactory( apolloHover: undefined as FeatureAndGlyphUnderMouse | undefined, })) .views((self) => ({ - getMousePosition(event: CanvasMouseEvent): MousePosition { + async getMousePosition(event: CanvasMouseEvent): Promise { const mousePosition = getMousePosition(event, self.lgv) const { bp, regionNumber, y } = mousePosition const row = Math.floor(y / self.apolloRowHeight) @@ -148,10 +148,11 @@ export function mouseEventsModelIntermediateFactory( } const [featureRow, topLevelFeature] = foundFeature const glyph = getGlyph(topLevelFeature) - const feature = glyph.getFeatureFromLayout( + const feature = await glyph.getFeatureFromLayout( topLevelFeature, bp, featureRow, + self.session.apolloDataStore.ontologyManager, ) if (!feature) { return mousePosition @@ -389,8 +390,8 @@ export function mouseEventsModelFactory( }, })) .actions((self) => ({ - onMouseDown(event: CanvasMouseEvent) { - const mousePosition = self.getMousePosition(event) + async onMouseDown(event: CanvasMouseEvent) { + const mousePosition = await self.getMousePosition(event) if (isMousePositionWithFeatureAndGlyph(mousePosition)) { mousePosition.featureAndGlyphUnderMouse.glyph.onMouseDown( self, @@ -399,8 +400,8 @@ export function mouseEventsModelFactory( ) } }, - onMouseMove(event: CanvasMouseEvent) { - const mousePosition = self.getMousePosition(event) + async onMouseMove(event: CanvasMouseEvent) { + const mousePosition = await self.getMousePosition(event) if (self.apolloDragging) { self.setCursor('col-resize') self.continueDrag(mousePosition, event) @@ -417,11 +418,11 @@ export function mouseEventsModelFactory( self.setCursor() } }, - onMouseLeave(event: CanvasMouseEvent) { + async onMouseLeave(event: CanvasMouseEvent) { self.setDragging() self.setApolloHover() - const mousePosition = self.getMousePosition(event) + const mousePosition = await self.getMousePosition(event) if (isMousePositionWithFeatureAndGlyph(mousePosition)) { mousePosition.featureAndGlyphUnderMouse.glyph.onMouseLeave( self, @@ -430,8 +431,8 @@ export function mouseEventsModelFactory( ) } }, - onMouseUp(event: CanvasMouseEvent) { - const mousePosition = self.getMousePosition(event) + async onMouseUp(event: CanvasMouseEvent) { + const mousePosition = await self.getMousePosition(event) if (isMousePositionWithFeatureAndGlyph(mousePosition)) { mousePosition.featureAndGlyphUnderMouse.glyph.onMouseUp( self, @@ -450,7 +451,7 @@ export function mouseEventsModelFactory( addDisposer( self, autorun( - () => { + async () => { // This type is wrong in @jbrowse/core // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!self.lgv.initialized || self.regionCannotBeRendered()) { @@ -464,7 +465,8 @@ export function mouseEventsModelFactory( 0, 0, self.lgv.dynamicBlocks.totalWidthPx, - self.featuresHeight, + + self.getFeaturesHeight(), ) const { apolloDragging, apolloHover } = self @@ -474,10 +476,10 @@ export function mouseEventsModelFactory( const { glyph } = apolloHover // draw mouseover hovers - glyph.drawHover(self, ctx) + await glyph.drawHover(self, ctx) // draw tooltip on hover - glyph.drawTooltip(self, ctx) + await glyph.drawTooltip(self, ctx) // dragging previews if (apolloDragging) { diff --git a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/stateModel/rendering.ts b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/stateModel/rendering.ts index 35cb0b322..be6768dcc 100644 --- a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/stateModel/rendering.ts +++ b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/stateModel/rendering.ts @@ -37,7 +37,7 @@ export function renderingModelIntermediateFactory( theme: undefined as Theme | undefined, })) .views((self) => ({ - get featuresHeight() { + getFeaturesHeight() { return ( (self.highestRow + 1) * self.apolloRowHeight + self.lastRowTooltipBufferHeight @@ -90,7 +90,7 @@ export function renderingModelIntermediateFactory( 0, 0, self.lgv.dynamicBlocks.totalWidthPx, - self.featuresHeight, + self.getFeaturesHeight(), ) for (const collaborator of ( self.session as unknown as ApolloSessionModel @@ -399,8 +399,9 @@ export function renderingModelFactory( addDisposer( self, autorun( - () => { - const { canvas, featureLayouts, featuresHeight, lgv } = self + async () => { + const featuresHeight = self.getFeaturesHeight() + const { canvas, featureLayouts, lgv } = self if (!lgv.initialized || self.regionCannotBeRendered()) { return } @@ -428,7 +429,7 @@ export function renderingModelFactory( ) { continue } - getGlyph(feature).draw(ctx, feature, row, self, idx) + await getGlyph(feature).draw(ctx, feature, row, self, idx) } } } diff --git a/packages/jbrowse-plugin-apollo/src/OntologyManager/index.ts b/packages/jbrowse-plugin-apollo/src/OntologyManager/index.ts index d10f0edf6..d22333785 100644 --- a/packages/jbrowse-plugin-apollo/src/OntologyManager/index.ts +++ b/packages/jbrowse-plugin-apollo/src/OntologyManager/index.ts @@ -114,6 +114,21 @@ export const OntologyManagerType = types expandPrefixes(uri: string) { return expandPrefixes(uri, self.prefixes) }, + /** + * Return true if `queryType` is a type of `typeOf`. + * E.g. isTypeOf('protein_coding_gene', 'gene') = true + * */ + async isTypeOf(queryType: string, typeOf: string): Promise { + const os = this.featureTypeOntology?.dataStore + if (!os) { + throw new Error(`Ontology ${self.featureTypeOntologyName} is undefined`) + } + const types = await os.getTermsWithLabelOrSynonym(typeOf) + const lbl: string[] = types + .map((x) => x.lbl) + .filter((x) => x != undefined) + return lbl.includes(queryType) + }, })) .actions((self) => ({ addOntology( diff --git a/packages/jbrowse-plugin-apollo/src/makeDisplayComponent.tsx b/packages/jbrowse-plugin-apollo/src/makeDisplayComponent.tsx index 117e30fcd..63e40257b 100644 --- a/packages/jbrowse-plugin-apollo/src/makeDisplayComponent.tsx +++ b/packages/jbrowse-plugin-apollo/src/makeDisplayComponent.tsx @@ -54,13 +54,13 @@ const useStyles = makeStyles()((theme) => ({ }, })) -function scrollSelectedFeatureIntoView( +async function scrollSelectedFeatureIntoView( model: LinearApolloDisplayI, scrollContainerRef: React.RefObject, ) { const { apolloRowHeight, selectedFeature } = model if (scrollContainerRef.current && selectedFeature) { - const position = model.getFeatureLayoutPosition(selectedFeature) + const position = await model.getFeatureLayoutPosition(selectedFeature) if (position) { const row = position.layoutRow + position.featureRow const top = row * apolloRowHeight @@ -170,7 +170,9 @@ export const DisplayComponent = observer(function DisplayComponent({ const canvasScrollContainerRef = useRef(null) useEffect(() => { - scrollSelectedFeatureIntoView(model, canvasScrollContainerRef) + void (async () => { + await scrollSelectedFeatureIntoView(model, canvasScrollContainerRef) + })() }, [model, selectedFeature]) const onDetailsResize = (delta: number) => {