From 3a294c5414e1cb3df5d3df31b7f80d4b145a4f9f Mon Sep 17 00:00:00 2001 From: EthanHealy01 Date: Tue, 25 Nov 2025 12:55:59 +0000 Subject: [PATCH] change requests --- .../public/locales/en-GB/translation.json | 8 +++++ frontend/src/core/auth/UseSession.tsx | 34 ------------------- .../InitialOnboardingModal/index.tsx | 8 +++-- .../InitialOnboardingModal/renderButtons.tsx | 14 ++++++-- .../useInitialOnboardingState.ts | 17 +++++----- .../onboarding/ServerLicenseModal.tsx | 3 +- .../onboarding/hooks/useOnboardingFlow.ts | 13 ++----- .../onboarding/onboardingFlowConfig.ts | 18 +++++----- frontend/src/core/constants/downloads.ts | 10 ++++++ frontend/src/core/services/updateService.ts | 12 +++---- 10 files changed, 63 insertions(+), 74 deletions(-) delete mode 100644 frontend/src/core/auth/UseSession.tsx create mode 100644 frontend/src/core/constants/downloads.ts diff --git a/frontend/public/locales/en-GB/translation.json b/frontend/public/locales/en-GB/translation.json index 9a5f238df..8dbc558db 100644 --- a/frontend/public/locales/en-GB/translation.json +++ b/frontend/public/locales/en-GB/translation.json @@ -5140,6 +5140,14 @@ "finish": "Finish", "startTour": "Start Tour", "startTourDescription": "Take a guided tour of Stirling PDF's key features", + "buttons": { + "next": "Next →", + "back": "Back", + "skipForNow": "Skip for now", + "download": "Download →", + "showMeAround": "Show me around", + "skipTheTour": "Skip the tour" + }, "serverLicense": { "skip": "Skip for now", "seePlans": "See Plans →", diff --git a/frontend/src/core/auth/UseSession.tsx b/frontend/src/core/auth/UseSession.tsx deleted file mode 100644 index 4cdfed453..000000000 --- a/frontend/src/core/auth/UseSession.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { createContext, useContext, type ReactNode } from 'react'; - -interface AuthContextValue { - session: null; - user: null; - loading: boolean; - error: null; - signOut: () => Promise; - refreshSession: () => Promise; -} - -const defaultValue: AuthContextValue = { - session: null, - user: null, - loading: false, - error: null, - signOut: async () => {}, - refreshSession: async () => {}, -}; - -const AuthContext = createContext(defaultValue); - -export function AuthProvider({ children }: { children: ReactNode }) { - return {children}; -} - -export function useAuth(): AuthContextValue { - return useContext(AuthContext); -} - -export function useAuthDebug(): AuthContextValue { - return useAuth(); -} - diff --git a/frontend/src/core/components/onboarding/InitialOnboardingModal/index.tsx b/frontend/src/core/components/onboarding/InitialOnboardingModal/index.tsx index 808f7a7f2..0ab33cfed 100644 --- a/frontend/src/core/components/onboarding/InitialOnboardingModal/index.tsx +++ b/frontend/src/core/components/onboarding/InitialOnboardingModal/index.tsx @@ -8,6 +8,8 @@ import { renderButtons } from '@app/components/onboarding/InitialOnboardingModal import styles from '@app/components/onboarding/InitialOnboardingModal/InitialOnboardingModal.module.css'; import type { InitialOnboardingModalProps } from '@app/components/onboarding/InitialOnboardingModal/types'; import { useInitialOnboardingState } from '@app/components/onboarding/InitialOnboardingModal/useInitialOnboardingState'; +import { BASE_PATH } from '@app/constants/app'; +import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '@app/styles/zIndex'; export default function InitialOnboardingModal(props: InitialOnboardingModalProps) { const flow = useInitialOnboardingState(props); @@ -32,7 +34,7 @@ export default function InitialOnboardingModal(props: InitialOnboardingModalProp return (
- Stirling icon + Stirling icon
); @@ -48,7 +50,7 @@ export default function InitialOnboardingModal(props: InitialOnboardingModalProp )} {slideDefinition.hero.type === 'diamond' && } {slideDefinition.hero.type === 'logo' && ( - Stirling logo + Stirling logo )} ); @@ -63,7 +65,7 @@ export default function InitialOnboardingModal(props: InitialOnboardingModalProp size="lg" radius="lg" withCloseButton={false} - zIndex={1001} + zIndex={Z_INDEX_OVER_FULLSCREEN_SURFACE} styles={{ body: { padding: 0 }, content: { overflow: 'hidden', border: 'none', background: 'var(--bg-surface)' }, diff --git a/frontend/src/core/components/onboarding/InitialOnboardingModal/renderButtons.tsx b/frontend/src/core/components/onboarding/InitialOnboardingModal/renderButtons.tsx index 428a27df1..4325d9b2f 100644 --- a/frontend/src/core/components/onboarding/InitialOnboardingModal/renderButtons.tsx +++ b/frontend/src/core/components/onboarding/InitialOnboardingModal/renderButtons.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { Button, Group, ActionIcon } from '@mantine/core'; import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'; +import { useTranslation } from 'react-i18next'; import { ButtonDefinition, type FlowState } from '@app/components/onboarding/onboardingFlowConfig'; import type { LicenseNotice } from '@app/types/types'; import type { ButtonAction } from '@app/components/onboarding/onboardingFlowConfig'; @@ -16,6 +17,7 @@ interface RenderButtonsProps { } export function renderButtons({ slideDefinition, licenseNotice, flowState, onAction }: RenderButtonsProps) { + const { t } = useTranslation(); const leftButtons = slideDefinition.buttons.filter((btn) => btn.group === 'left'); const rightButtons = slideDefinition.buttons.filter((btn) => btn.group === 'right'); @@ -36,15 +38,23 @@ export function renderButtons({ slideDefinition, licenseNotice, flowState, onAct }; const resolveButtonLabel = (button: ButtonDefinition) => { + // Special case: override "See Plans" with "Upgrade now" when over limit if ( button.type === 'button' && slideDefinition.id === 'server-license' && button.action === 'see-plans' && licenseNotice.isOverLimit ) { - return 'Upgrade now →'; + return t('onboarding.serverLicense.upgrade', 'Upgrade now →'); } - return button.label ?? ''; + + // Translate the label (it's a translation key) + const label = button.label ?? ''; + if (!label) return ''; + + // Extract fallback text from translation key (e.g., 'onboarding.buttons.next' -> 'Next') + const fallback = label.split('.').pop() || label; + return t(label, fallback); }; const renderButton = (button: ButtonDefinition) => { diff --git a/frontend/src/core/components/onboarding/InitialOnboardingModal/useInitialOnboardingState.ts b/frontend/src/core/components/onboarding/InitialOnboardingModal/useInitialOnboardingState.ts index 7e2f7c434..066a777cc 100644 --- a/frontend/src/core/components/onboarding/InitialOnboardingModal/useInitialOnboardingState.ts +++ b/frontend/src/core/components/onboarding/InitialOnboardingModal/useInitialOnboardingState.ts @@ -13,6 +13,7 @@ import type { LicenseNotice } from '@app/types/types'; import { resolveFlow } from '@app/components/onboarding/InitialOnboardingModal/flowResolver'; import { useServerExperience } from '@app/hooks/useServerExperience'; import { DEFAULT_STATE, type InitialOnboardingModalProps, type OnboardingState } from '@app/components/onboarding/InitialOnboardingModal/types'; +import { DOWNLOAD_URLS } from '@app/constants/downloads'; interface UseInitialOnboardingStateResult { state: OnboardingState; @@ -112,14 +113,14 @@ export function useInitialOnboardingState({ const os = useMemo(() => { switch (osType) { case 'windows': - return { label: 'Windows', url: 'https://files.stirlingpdf.com/win-installer.exe' }; + return { label: 'Windows', url: DOWNLOAD_URLS.WINDOWS }; case 'mac-apple': - return { label: 'Mac (Apple Silicon)', url: 'https://files.stirlingpdf.com/mac-installer.dmg' }; + return { label: 'Mac (Apple Silicon)', url: DOWNLOAD_URLS.MAC_APPLE_SILICON }; case 'mac-intel': - return { label: 'Mac (Intel)', url: 'https://files.stirlingpdf.com/mac-x86_64-installer.dmg' }; + return { label: 'Mac (Intel)', url: DOWNLOAD_URLS.MAC_INTEL }; case 'linux-x64': case 'linux-arm64': - return { label: 'Linux', url: 'https://docs.stirlingpdf.com/Installation/Unix%20Installation/' }; + return { label: 'Linux', url: DOWNLOAD_URLS.LINUX_DOCS }; default: return { label: '', url: '' }; } @@ -127,10 +128,10 @@ export function useInitialOnboardingState({ const osOptions = useMemo(() => { const options = [ - { label: 'Windows', url: 'https://files.stirlingpdf.com/win-installer.exe', value: 'windows' }, - { label: 'Mac (Apple Silicon)', url: 'https://files.stirlingpdf.com/mac-installer.dmg', value: 'mac-apple' }, - { label: 'Mac (Intel)', url: 'https://files.stirlingpdf.com/mac-x86_64-installer.dmg', value: 'mac-intel' }, - { label: 'Linux', url: 'https://docs.stirlingpdf.com/Installation/Unix%20Installation/', value: 'linux' }, + { label: 'Windows', url: DOWNLOAD_URLS.WINDOWS, value: 'windows' }, + { label: 'Mac (Apple Silicon)', url: DOWNLOAD_URLS.MAC_APPLE_SILICON, value: 'mac-apple' }, + { label: 'Mac (Intel)', url: DOWNLOAD_URLS.MAC_INTEL, value: 'mac-intel' }, + { label: 'Linux', url: DOWNLOAD_URLS.LINUX_DOCS, value: 'linux' }, ]; return options.filter(opt => opt.url); }, []); diff --git a/frontend/src/core/components/onboarding/ServerLicenseModal.tsx b/frontend/src/core/components/onboarding/ServerLicenseModal.tsx index 43f6d4897..9c53628cb 100644 --- a/frontend/src/core/components/onboarding/ServerLicenseModal.tsx +++ b/frontend/src/core/components/onboarding/ServerLicenseModal.tsx @@ -5,6 +5,7 @@ import AnimatedSlideBackground from '@app/components/onboarding/slides/AnimatedS import ServerLicenseSlide from '@app/components/onboarding/slides/ServerLicenseSlide'; import { LicenseNotice } from '@app/types/types'; import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '@app/styles/zIndex'; +import { BASE_PATH } from '@app/constants/app'; import styles from '@app/components/onboarding/InitialOnboardingModal/InitialOnboardingModal.module.css'; interface ServerLicenseModalProps { @@ -71,7 +72,7 @@ export default function ServerLicenseModal({ />
- Stirling logo + Stirling logo
diff --git a/frontend/src/core/components/onboarding/hooks/useOnboardingFlow.ts b/frontend/src/core/components/onboarding/hooks/useOnboardingFlow.ts index e914deea5..18dec59fc 100644 --- a/frontend/src/core/components/onboarding/hooks/useOnboardingFlow.ts +++ b/frontend/src/core/components/onboarding/hooks/useOnboardingFlow.ts @@ -3,7 +3,6 @@ import { usePreferences } from '@app/contexts/PreferencesContext'; import { useAppConfig } from '@app/contexts/AppConfigContext'; import { useCookieConsentContext } from '@app/contexts/CookieConsentContext'; import { useOnboarding } from '@app/contexts/OnboardingContext'; -import { useAuth } from '@app/auth/UseSession'; import type { LicenseNotice } from '@app/types/types'; import { useNavigate } from 'react-router-dom'; import { @@ -33,16 +32,8 @@ export function useOnboardingFlow() { const { config } = useAppConfig(); const { showCookieConsent, isReady: isCookieConsentReady } = useCookieConsentContext(); const { completeTour, tourType, isOpen } = useOnboarding(); - let session: any = null; - try { - session = useAuth()?.session ?? null; - } catch { - session = {} as any; - } - - const loginEnabled = !!config?.enableLogin; - const isAuthenticated = !!session; - const shouldShowIntro = !preferences.hasSeenIntroOnboarding && (!loginEnabled || isAuthenticated); + + const shouldShowIntro = !preferences.hasSeenIntroOnboarding; const isAdminUser = !!config?.isAdmin; const { hasPaidLicense } = useServerExperience(); diff --git a/frontend/src/core/components/onboarding/onboardingFlowConfig.ts b/frontend/src/core/components/onboarding/onboardingFlowConfig.ts index 30967691d..f9c08eb60 100644 --- a/frontend/src/core/components/onboarding/onboardingFlowConfig.ts +++ b/frontend/src/core/components/onboarding/onboardingFlowConfig.ts @@ -79,7 +79,7 @@ export const SLIDE_DEFINITIONS: Record = { { key: 'welcome-next', type: 'button', - label: 'Next →', + label: 'onboarding.buttons.next', variant: 'primary', group: 'right', action: 'next', @@ -101,7 +101,7 @@ export const SLIDE_DEFINITIONS: Record = { { key: 'desktop-skip', type: 'button', - label: 'Skip for now', + label: 'onboarding.buttons.skipForNow', variant: 'secondary', group: 'left', action: 'next', @@ -109,7 +109,7 @@ export const SLIDE_DEFINITIONS: Record = { { key: 'desktop-download', type: 'button', - label: 'Download →', + label: 'onboarding.buttons.download', variant: 'primary', group: 'right', action: 'download-selected', @@ -125,7 +125,7 @@ export const SLIDE_DEFINITIONS: Record = { { key: 'security-back', type: 'button', - label: 'Back', + label: 'onboarding.buttons.back', variant: 'secondary', group: 'left', action: 'prev', @@ -133,7 +133,7 @@ export const SLIDE_DEFINITIONS: Record = { { key: 'security-next', type: 'button', - label: 'Next →', + label: 'onboarding.buttons.next', variant: 'primary', group: 'right', action: 'security-next', @@ -157,7 +157,7 @@ export const SLIDE_DEFINITIONS: Record = { { key: 'admin-show', type: 'button', - label: 'Show me around', + label: 'onboarding.buttons.showMeAround', variant: 'primary', group: 'right', action: 'launch-admin', @@ -165,7 +165,7 @@ export const SLIDE_DEFINITIONS: Record = { { key: 'admin-skip', type: 'button', - label: 'Skip the tour', + label: 'onboarding.buttons.skipTheTour', variant: 'secondary', group: 'left', action: 'skip-to-license', @@ -180,7 +180,7 @@ export const SLIDE_DEFINITIONS: Record = { { key: 'license-close', type: 'button', - label: 'Skip for now', + label: 'onboarding.buttons.skipForNow', variant: 'secondary', group: 'left', action: 'close', @@ -188,7 +188,7 @@ export const SLIDE_DEFINITIONS: Record = { { key: 'license-see-plans', type: 'button', - label: 'See Plans →', + label: 'onboarding.serverLicense.seePlans', variant: 'primary', group: 'right', action: 'see-plans', diff --git a/frontend/src/core/constants/downloads.ts b/frontend/src/core/constants/downloads.ts new file mode 100644 index 000000000..5eee10a28 --- /dev/null +++ b/frontend/src/core/constants/downloads.ts @@ -0,0 +1,10 @@ +// Centralized download URLs for Stirling PDF desktop installers +export const DOWNLOAD_URLS = { + WINDOWS: 'https://files.stirlingpdf.com/win-installer.exe', + MAC_APPLE_SILICON: 'https://files.stirlingpdf.com/mac-installer.dmg', + MAC_INTEL: 'https://files.stirlingpdf.com/mac-x86_64-installer.dmg', + LINUX_DOCS: 'https://docs.stirlingpdf.com/Installation/Unix%20Installation/', +} as const; + +export const DOWNLOAD_BASE_URL = 'https://files.stirlingpdf.com/'; + diff --git a/frontend/src/core/services/updateService.ts b/frontend/src/core/services/updateService.ts index f134e403e..343898232 100644 --- a/frontend/src/core/services/updateService.ts +++ b/frontend/src/core/services/updateService.ts @@ -1,3 +1,5 @@ +import { DOWNLOAD_BASE_URL } from '@app/constants/downloads'; + export interface UpdateSummary { latest_version: string | null; latest_stable_version?: string | null; @@ -71,11 +73,9 @@ export class UpdateService { return null; } - const baseUrl = 'https://files.stirlingpdf.com/'; - // Determine file based on machine type and security if (machineInfo.machineType === 'Server-jar') { - return baseUrl + (machineInfo.activeSecurity ? 'Stirling-PDF-with-login.jar' : 'Stirling-PDF.jar'); + return DOWNLOAD_BASE_URL + (machineInfo.activeSecurity ? 'Stirling-PDF-with-login.jar' : 'Stirling-PDF.jar'); } // Client installations @@ -84,11 +84,11 @@ export class UpdateService { const type = machineInfo.activeSecurity ? '-server-security' : '-server'; if (os === 'unix') { - return baseUrl + os + type + '.jar'; + return DOWNLOAD_BASE_URL + os + type + '.jar'; } else if (os === 'win') { - return baseUrl + os + '-installer.exe'; + return DOWNLOAD_BASE_URL + os + '-installer.exe'; } else if (os === 'mac') { - return baseUrl + os + '-installer.dmg'; + return DOWNLOAD_BASE_URL + os + '-installer.dmg'; } }