| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- import { sendSearchEvent } from '@/features/event-tracking/search-events'
- import OLButton from '@/features/ui/components/ol/ol-button'
- import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
- import { useLayoutContext } from '@/shared/context/layout-context'
- import { closeSearchPanel, SearchQuery } from '@codemirror/search'
- import { forwardRef, memo, Ref, useCallback, useEffect, useRef } from 'react'
- import { useCodeMirrorViewContext } from './codemirror-context'
- import MaterialIcon from '@/shared/components/material-icon'
- import { useTranslation } from 'react-i18next'
- import { Overlay, Popover } from 'react-bootstrap'
- import Close from '@/shared/components/close'
- import useTutorial from '@/shared/hooks/promotions/use-tutorial'
- import { useEditorContext } from '@/shared/context/editor-context'
- import getMeta from '@/utils/meta'
- import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
- import { useRailContext } from '@/features/ide-redesign/contexts/rail-context'
- const PROMOTION_SIGNUP_CUT_OFF_DATE = new Date('2025-04-22T00:00:00Z')
- export const FullProjectSearchButton = ({ query }: { query: SearchQuery }) => {
- const view = useCodeMirrorViewContext()
- const { t } = useTranslation()
- const { setProjectSearchIsOpen } = useLayoutContext()
- const newEditor = useIsNewEditorEnabled()
- const { openTab } = useRailContext()
- const ref = useRef<HTMLButtonElement>(null)
- const { inactiveTutorials } = useEditorContext()
- const hasCompletedTutorial = inactiveTutorials.includes(
- 'full-project-search-promo'
- )
- const { showPopup, tryShowingPopup, hideUntilReload, completeTutorial } =
- useTutorial('full-project-search-promo', {
- name: 'full-project-search-promotion',
- })
- let isEligibleForPromotion = true
- const signUpDateString = getMeta('ol-user')?.signUpDate
- if (!signUpDateString) {
- isEligibleForPromotion = false
- } else {
- const signupDate = new Date(signUpDateString)
- if (signupDate > PROMOTION_SIGNUP_CUT_OFF_DATE) {
- isEligibleForPromotion = false
- }
- }
- const openFullProjectSearch = useCallback(() => {
- if (newEditor) {
- openTab('full-project-search')
- } else {
- setProjectSearchIsOpen(true)
- }
- closeSearchPanel(view)
- window.setTimeout(() => {
- window.dispatchEvent(
- new CustomEvent('editor:full-project-search', { detail: query })
- )
- }, 200)
- }, [setProjectSearchIsOpen, query, view, newEditor, openTab])
- const onClick = useCallback(() => {
- sendSearchEvent('search-open', {
- searchType: 'full-project',
- method: 'button',
- location: 'search-form',
- })
- openFullProjectSearch()
- if (!hasCompletedTutorial && isEligibleForPromotion) {
- completeTutorial({ action: 'complete', event: 'promo-click' })
- }
- }, [
- completeTutorial,
- openFullProjectSearch,
- hasCompletedTutorial,
- isEligibleForPromotion,
- ])
- return (
- <>
- <OLTooltip
- id="open-full-project-search"
- overlayProps={{ placement: 'bottom' }}
- description={t('search_all_project_files')}
- >
- <OLButton variant="secondary" size="sm" ref={ref} onClick={onClick}>
- <MaterialIcon
- type="manage_search"
- accessibilityLabel={t('search_all_project_files')}
- />
- </OLButton>
- </OLTooltip>
- {!hasCompletedTutorial && isEligibleForPromotion && (
- <PromotionOverlay
- ref={ref}
- showPopup={showPopup}
- tryShowingPopup={tryShowingPopup}
- completeTutorial={completeTutorial}
- hideUntilReload={hideUntilReload}
- />
- )}
- </>
- )
- }
- type PromotionOverlayProps = {
- showPopup: boolean
- tryShowingPopup: () => void
- completeTutorial: (event: {
- action: 'complete'
- event: 'promo-dismiss'
- }) => void
- hideUntilReload: () => void
- }
- const PromotionOverlay = forwardRef<HTMLButtonElement, PromotionOverlayProps>(
- function PromotionOverlay(
- props: PromotionOverlayProps,
- ref: Ref<HTMLButtonElement>
- ) {
- if (typeof ref === 'function' || !ref?.current) {
- return null
- }
- return <PromotionContent target={ref.current} {...props} />
- }
- )
- const PromotionContent = memo(function PromotionContent({
- showPopup,
- tryShowingPopup,
- completeTutorial,
- hideUntilReload,
- target,
- }: PromotionOverlayProps & {
- target: HTMLButtonElement
- }) {
- const { t } = useTranslation()
- useEffect(() => {
- tryShowingPopup()
- }, [tryShowingPopup])
- const onHide = useCallback(() => {
- hideUntilReload()
- }, [hideUntilReload])
- const onClose = useCallback(() => {
- completeTutorial({
- action: 'complete',
- event: 'promo-dismiss',
- })
- }, [completeTutorial])
- return (
- <Overlay
- placement="top"
- show={showPopup}
- target={target}
- rootClose
- onHide={onHide}
- >
- <Popover>
- <Popover.Body>
- <Close variant="dark" onDismiss={onClose} />
- {t('now_you_can_search_your_whole_project_not_just_this_file')}
- </Popover.Body>
- </Popover>
- </Overlay>
- )
- })
|