Merge pull request #26100 from overleaf/dp-compile-timeout-paywall

Add compile timeout paywall to new editor

GitOrigin-RevId: 9742ae67b4103c72cc9d87852801ae8751f85d6d
This commit is contained in:
David
2025-06-04 10:47:18 +01:00
committed by Copybot
parent 08316442cf
commit a8a21e05af
4 changed files with 100 additions and 29 deletions

View File

@@ -287,6 +287,8 @@
"compile_error_entry_description": "",
"compile_error_handling": "",
"compile_larger_projects": "",
"compile_limit_reached": "",
"compile_limit_upgrade_prompt": "",
"compile_mode": "",
"compile_terminated_by_user": "",
"compiler": "",

View File

@@ -5,31 +5,37 @@ import { useRailContext } from '../../contexts/rail-context'
import { usePdfPreviewContext } from '@/features/pdf-preview/components/pdf-preview-provider'
import { useDetachCompileContext as useCompileContext } from '@/shared/context/detach-compile-context'
import { useIsNewEditorEnabled } from '../../utils/new-editor-utils'
import { upgradePlan } from '@/main/account-upgrade'
import classNames from 'classnames'
function PdfErrorState() {
const { loadingError } = usePdfPreviewContext()
// TODO ide-redesign-cleanup: rename showLogs to something else and check usages
const { showLogs } = useCompileContext()
const { t } = useTranslation()
const { openTab: openRailTab } = useRailContext()
const { hasShortCompileTimeout, error, showLogs } = useCompileContext()
const newEditor = useIsNewEditorEnabled()
if (!newEditor || (!loadingError && !showLogs)) {
return null
}
if (hasShortCompileTimeout && error === 'timedout') {
return <CompileTimeoutErrorState />
}
return <GeneralErrorState />
}
const GeneralErrorState = () => {
const { t } = useTranslation()
const { openTab: openRailTab } = useRailContext()
return (
<div className="pdf-error-state">
<div className="pdf-error-state-top-section">
<div className="pdf-error-state-warning-icon">
<MaterialIcon type="warning" />
</div>
<div className="pdf-error-state-text">
<p className="pdf-error-state-label">{t('pdf_couldnt_compile')}</p>
<p className="pdf-error-state-description">
{t('we_are_unable_to_generate_the_pdf_at_this_time')}
</p>
</div>
<ErrorState
title={t('pdf_couldnt_compile')}
description={t('we_are_unable_to_generate_the_pdf_at_this_time')}
iconType="warning"
iconClassName="pdf-error-state-warning-icon"
actions={
<OLButton
variant="secondary"
size="sm"
@@ -39,20 +45,74 @@ function PdfErrorState() {
>
{t('check_logs')}
</OLButton>
</div>
<div className="pdf-error-state-info-box">
<div className="pdf-error-state-info-box-title">
<MaterialIcon type="info" unfilled />
{t('why_might_this_happen')}
}
extraContent={
<div className="pdf-error-state-info-box">
<div className="pdf-error-state-info-box-title">
<MaterialIcon type="info" unfilled />
{t('why_might_this_happen')}
</div>
<ul className="pdf-error-state-info-box-text">
<li>{t('there_is_an_unrecoverable_latex_error')}</li>
<li>{t('the_document_environment_contains_no_content')}</li>
<li>{t('this_project_contains_a_file_called_output')}</li>
</ul>
</div>
<ul className="pdf-error-state-info-box-text">
<li>{t('there_is_an_unrecoverable_latex_error')}</li>
<li>{t('the_document_environment_contains_no_content')}</li>
<li>{t('this_project_contains_a_file_called_output')}</li>
</ul>
</div>
</div>
}
/>
)
}
const CompileTimeoutErrorState = () => {
const { t } = useTranslation()
return (
<ErrorState
title={t('compile_limit_reached')}
description={t('compile_limit_upgrade_prompt')}
iconType="running_with_errors"
actions={
<OLButton
variant="premium"
size="sm"
onClick={() => upgradePlan('compile-timeout')}
>
{t('upgrade')}
</OLButton>
}
/>
)
}
const ErrorState = ({
title,
description,
iconType,
actions,
iconClassName,
extraContent,
}: {
title: string
description: string
iconType: string
actions: React.ReactNode
iconClassName?: string
extraContent?: React.ReactNode
}) => {
return (
<div className="pdf-error-state">
<div className="pdf-error-state-top-section">
<div className={classNames('pdf-error-state-icon', iconClassName)}>
<MaterialIcon type={iconType} />
</div>
<div className="pdf-error-state-text">
<p className="pdf-error-state-label">{title}</p>
<p className="pdf-error-state-description">{description}</p>
</div>
{actions}
</div>
{extraContent}
</div>
)
}
export default PdfErrorState

View File

@@ -33,9 +33,7 @@
padding: 0 var(--spacing-09) var(--spacing-09) var(--spacing-09);
}
.pdf-error-state-warning-icon {
background-color: var(--bg-danger-03);
color: var(--content-danger);
.pdf-error-state-icon {
width: 80px;
height: 80px;
display: flex;
@@ -43,6 +41,15 @@
justify-content: center;
border-radius: 100%;
.material-symbols {
font-size: 80px;
}
}
.pdf-error-state-warning-icon {
background-color: var(--bg-danger-03);
color: var(--content-danger);
.material-symbols {
font-size: 32px;
}

View File

@@ -370,6 +370,8 @@
"compile_error_entry_description": "An error which prevented this project from compiling",
"compile_error_handling": "Compile error handling",
"compile_larger_projects": "Compile larger projects",
"compile_limit_reached": "Compile limit reached",
"compile_limit_upgrade_prompt": "Your document took longer than the free plans compile window. Upgrade to Overleaf Premium for extended compile durations, priority build servers, and uninterrupted LaTeX processing—so you can focus on writing, not waiting.",
"compile_mode": "Compile mode",
"compile_servers": "Compile servers",
"compile_servers_info_new": "The servers used to compile your project. Compiles for users on paid plans always run on the fastest available servers.",