change requests

This commit is contained in:
EthanHealy01
2025-11-25 12:55:59 +00:00
parent 71a6846378
commit 3a294c5414
10 changed files with 63 additions and 74 deletions

View File

@@ -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 →",

View File

@@ -1,34 +0,0 @@
import { createContext, useContext, type ReactNode } from 'react';
interface AuthContextValue {
session: null;
user: null;
loading: boolean;
error: null;
signOut: () => Promise<void>;
refreshSession: () => Promise<void>;
}
const defaultValue: AuthContextValue = {
session: null,
user: null,
loading: false,
error: null,
signOut: async () => {},
refreshSession: async () => {},
};
const AuthContext = createContext<AuthContextValue>(defaultValue);
export function AuthProvider({ children }: { children: ReactNode }) {
return <AuthContext.Provider value={defaultValue}>{children}</AuthContext.Provider>;
}
export function useAuth(): AuthContextValue {
return useContext(AuthContext);
}
export function useAuthDebug(): AuthContextValue {
return useAuth();
}

View File

@@ -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 (
<div className={styles.heroIconsContainer}>
<div className={styles.iconWrapper}>
<img src="/branding/StirlingLogoLegacy.svg" alt="Stirling icon" className={styles.downloadIcon} />
<img src={`${BASE_PATH}/branding/StirlingLogoLegacy.svg`} alt="Stirling icon" className={styles.downloadIcon} />
</div>
</div>
);
@@ -48,7 +50,7 @@ export default function InitialOnboardingModal(props: InitialOnboardingModalProp
)}
{slideDefinition.hero.type === 'diamond' && <DiamondOutlinedIcon sx={{ fontSize: 64, color: '#000000' }} />}
{slideDefinition.hero.type === 'logo' && (
<img src="/branding/StirlingPDFLogoNoTextLightHC.svg" alt="Stirling logo" />
<img src={`${BASE_PATH}/branding/StirlingPDFLogoNoTextLightHC.svg`} alt="Stirling logo" />
)}
</div>
);
@@ -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)' },

View File

@@ -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) => {

View File

@@ -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);
}, []);

View File

@@ -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({
/>
<div className={styles.heroLogo}>
<div className={styles.heroLogoCircle}>
<img src="/branding/StirlingPDFLogoNoTextLightHC.svg" alt="Stirling logo" />
<img src={`${BASE_PATH}/branding/StirlingPDFLogoNoTextLightHC.svg`} alt="Stirling logo" />
</div>
</div>
</div>

View File

@@ -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();

View File

@@ -79,7 +79,7 @@ export const SLIDE_DEFINITIONS: Record<SlideId, SlideDefinition> = {
{
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<SlideId, SlideDefinition> = {
{
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<SlideId, SlideDefinition> = {
{
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<SlideId, SlideDefinition> = {
{
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<SlideId, SlideDefinition> = {
{
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<SlideId, SlideDefinition> = {
{
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<SlideId, SlideDefinition> = {
{
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<SlideId, SlideDefinition> = {
{
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<SlideId, SlideDefinition> = {
{
key: 'license-see-plans',
type: 'button',
label: 'See Plans',
label: 'onboarding.serverLicense.seePlans',
variant: 'primary',
group: 'right',
action: 'see-plans',

View File

@@ -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/';

View File

@@ -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';
}
}