Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const nextCloseButtonClick = closeButtonClicks.next.bind(closeButtonClicks)
/** Emits whenever the ref callback for the hover element is called */
const hoverOverlayElements = new Subject()
const nextOverlayElement = hoverOverlayElements.next.bind(hoverOverlayElements)
const relativeElement = document.body
const containerComponentUpdates = new Subject()
subscription.add(
registerHoverContributions({ extensionsController, platformContext, history: H.createBrowserHistory() })
)
// Code views come and go, but there is always a single hoverifier on the page
const hoverifier = createHoverifier<
RepoSpec & RevSpec & FileSpec & ResolvedRevSpec,
HoverData,
ActionItemAction
>({
closeButtonClicks,
hoverOverlayElements,
hoverOverlayRerenders: containerComponentUpdates.pipe(
withLatestFrom(hoverOverlayElements),
map(([, hoverOverlayElement]) => ({ hoverOverlayElement, relativeElement })),
filter(propertyIsDefined('hoverOverlayElement'))
),
getHover: ({ line, character, part, ...rest }) =>
combineLatest([
getHover({ ...rest, position: { line, character } }),
getActiveHoverAlerts(hoverAlerts),
]).pipe(
constructor(props: RepositoryCompareAreaProps) {
super(props)
this.hoverifier = createHoverifier<
RepoSpec & RevSpec & FileSpec & ResolvedRevSpec,
HoverMerged,
ActionItemAction
>({
closeButtonClicks: this.closeButtonClicks,
hoverOverlayElements: this.hoverOverlayElements,
hoverOverlayRerenders: this.componentUpdates.pipe(
withLatestFrom(this.hoverOverlayElements, this.repositoryCompareAreaElements),
map(([, hoverOverlayElement, repositoryCompareAreaElement]) => ({
hoverOverlayElement,
// The root component element is guaranteed to be rendered after a componentDidUpdate
relativeElement: repositoryCompareAreaElement!,
})),
// Can't reposition HoverOverlay if it wasn't rendered
filter(propertyIsDefined('hoverOverlayElement'))
),
constructor(props: BlobProps) {
super(props)
this.state = {
lineDecorationAttachmentIDs: {},
}
/** Emits parsed positions found in the URL */
const locationPositions: Observable = this.componentUpdates.pipe(
map(props => parseHash(props.location.hash)),
distinctUntilChanged((a, b) => isEqual(a, b)),
share()
)
const hoverifier = createHoverifier({
closeButtonClicks: this.closeButtonClicks,
goToDefinitionClicks: this.goToDefinitionClicks,
hoverOverlayElements: this.hoverOverlayElements,
hoverOverlayRerenders: this.componentUpdates.pipe(
withLatestFrom(this.hoverOverlayElements, this.blobElements),
// After componentDidUpdate, the blob element is guaranteed to have been rendered
map(([, hoverOverlayElement, blobElement]) => ({ hoverOverlayElement, relativeElement: blobElement! })),
// Can't reposition HoverOverlay if it wasn't rendered
filter(propertyIsDefined('hoverOverlayElement'))
),
pushHistory: path => this.props.history.push(path),
logTelemetryEvent,
fetchHover: position => getHover(this.getLSPTextDocumentPositionParams(position), this.props),
fetchJumpURL: position => getJumpURL(this.getLSPTextDocumentPositionParams(position), this.props),
})
this.subscriptions.add(hoverifier)
this.setState({ site })
},
() => {
this.setState({ site: undefined })
}
)
)
this.subscriptions.add(
// Ensure the site is valid.
fetchingSite
.pipe(
// Get the access token for this server if we have it.
switchMap(() => getAccessToken(sourcegraphUrl)),
switchMap(token => fetchCurrentUser(false).pipe(map(user => ({ user, token })))),
filter(propertyIsDefined('user')),
// Get the IDs for all access tokens for the user.
switchMap(({ token, user }) =>
fetchAccessTokenIDs(user.id).pipe(map(usersTokenIDs => ({ usersTokenIDs, user, token })))
),
// Make sure the token still exists on the server. If it
// does exits, use it, otherwise create a new one.
switchMap(({ user, token, usersTokenIDs }) => {
const tokenExists = token && usersTokenIDs.map(({ id }) => id).includes(token.id)
return token && tokenExists
? of(token)
: createAccessToken(user.id).pipe(
tap(createdToken => {
setAccessToken(sourcegraphUrl, createdToken)
})
)
props.setSourcegraphURL(url)
})
)
this.subscriptions.add(
// Ensure the site is valid.
fetchingSite
.pipe(
filter(urlOrError => !isErrorLike(urlOrError)),
map(urlOrError => urlOrError as string),
// Get the access token for this server if we have it.
switchMap(url => this.props.getAccessToken(url).pipe(map(token => ({ token, url })))),
switchMap(({ url, token }) =>
this.props.fetchCurrentUser(false).pipe(map(user => ({ user, token, url })))
),
filter(propertyIsDefined('user')),
// Get the IDs for all access tokens for the user.
switchMap(({ token, user, url }) =>
this.props
.fetchAccessTokenIDs(user.id)
.pipe(map(usersTokenIDs => ({ usersTokenIDs, user, token, url })))
),
// Make sure the token still exists on the server. If it
// does exits, use it, otherwise create a new one.
switchMap(({ user, token, usersTokenIDs, url }) => {
const tokenExists = token && usersTokenIDs.map(({ id }) => id).includes(token.id)
return token && tokenExists
? of(token)
: this.props.createAccessToken(user.id).pipe(this.props.setAccessToken(url))
})
)
fetchHover: position => getHover(this.getLSPTextDocumentPositionParams(position), this.props),
fetchJumpURL: position => getJumpURL(this.getLSPTextDocumentPositionParams(position), this.props),
})
this.subscriptions.add(hoverifier)
const resolveContext = () => ({
repoPath: this.props.repoPath,
rev: this.props.rev,
commitID: this.props.commitID,
filePath: this.props.filePath,
})
this.subscriptions.add(
hoverifier.hoverify({
positionEvents: this.codeViewElements.pipe(
filter(isDefined),
findPositionsFromEvents(domFunctions)
),
positionJumps: locationPositions.pipe(
withLatestFrom(this.codeViewElements, this.blobElements),
map(([position, codeView, scrollElement]) => ({
position,
// locationPositions is derived from componentUpdates,
// so these elements are guaranteed to have been rendered.
codeView: codeView!,
scrollElement: scrollElement!,
}))
),
resolveContext,
dom: domFunctions,
})
)
this.subscriptions.add(
map(({ hoverOverlayElement, codeIntellifyBlobElement }) => ({
hoverOverlayElement,
relativeElement: codeIntellifyBlobElement.closest(this.props.parentElement) as HTMLElement | null,
})),
// Can't reposition HoverOverlay or file weren't rendered
filter(propertyIsDefined('relativeElement')),
filter(propertyIsDefined('hoverOverlayElement'))
),
fetchHover: hoveredToken => getHover(this.getLSPTextDocumentPositionParams(hoveredToken), this.props),
fetchJumpURL: hoveredToken => getJumpURL(this.getLSPTextDocumentPositionParams(hoveredToken), this.props),
})
this.subscriptions.add(hoverifier)
const positionEvents = this.codeViewElements.pipe(
filter(isDefined),
findPositionsFromEvents(domFunctions)
)
const targets = positionEvents.pipe(map(({ event: { target } }) => target))
targets.subscribe(target => (this.target = target))
this.subscriptions.add(
hoverifier.hoverify({
positionEvents,
resolveContext: () => ({
repoPath: REPO_PATH,
commitID: COMMIT_ID,
rev: REV || '',
filePath: FILE_PATH,
}),
dom: domFunctions,
// After componentDidUpdate, the blob element is guaranteed to have been rendered
map(([, hoverOverlayElement, blobElement]) => ({ hoverOverlayElement, relativeElement: blobElement! })),
// Can't reposition HoverOverlay if it wasn't rendered
filter(propertyIsDefined('hoverOverlayElement'))
),
getHover: position => getHover(this.getLSPTextDocumentPositionParams(position), this.props),
getActions: context => getHoverActions(this.props, context),
pinningEnabled: !singleClickGoToDefinition,
})
this.subscriptions.add(hoverifier)
this.subscriptions.add(
hoverifier.hoverify({
positionEvents: this.codeViewElements.pipe(
filter(isDefined),
findPositionsFromEvents({ domFunctions })
),
positionJumps: locationPositions.pipe(
withLatestFrom(this.codeViewElements, this.blobElements),
map(([position, codeView, scrollElement]) => ({
position,
// locationPositions is derived from componentUpdates,
// so these elements are guaranteed to have been rendered.
codeView: codeView!,
scrollElement: scrollElement!,
}))
),
resolveContext: () => ({
repoName: this.props.repoName,
rev: this.props.rev,
commitID: this.props.commitID,
filePath: this.props.filePath,
map(({ hoverOverlayElement, codeIntellifyBlobElement }) => ({
hoverOverlayElement,
relativeElement: codeIntellifyBlobElement.closest(this.props.parentElement) as HTMLElement | null,
})),
// Can't reposition HoverOverlay or file weren't rendered
filter(propertyIsDefined('relativeElement')),
filter(propertyIsDefined('hoverOverlayElement'))
),
getHover: hoveredToken => getHover(this.getLSPTextDocumentPositionParams(hoveredToken), this.props),
getActions: context => getHoverActions(this.props, context),
})
this.subscriptions.add(hoverifier)
const positionEvents = this.codeViewElements.pipe(
filter(isDefined),
findPositionsFromEvents(domFunctions)
)
const targets = positionEvents.pipe(map(({ event: { target } }) => target))
targets.subscribe(target => (this.target = target))
this.subscriptions.add(
hoverifier.hoverify({
positionEvents,
resolveContext: () => ({
repoName: REPO_NAME,
commitID: COMMIT_ID,
rev: REV || '',
filePath: FILE_PATH,
}),
dom: domFunctions,
constructor(props: Props) {
super(props)
this.state = {
hoverOverlayIsFixed: false,
clickedGoToDefinition: false,
mouseIsMoving: false,
}
this.subscriptions.add(
this.props.hoverifier.hoverify({
dom: diffDomFunctions,
positionEvents: this.codeElements.pipe(
filter(isDefined),
findPositionsFromEvents(diffDomFunctions)
),
positionJumps: NEVER, // TODO support diff URLs
resolveContext: hoveredToken => {
// if part is undefined, it doesn't matter whether we chose head or base, the line stayed the same
const { repoPath, rev, filePath, commitID } = this.props[hoveredToken.part || 'head']
// If a hover or go-to-definition was invoked on this part, we know the file path must exist
return { repoPath, filePath: filePath!, rev, commitID }
},
})
)
}