mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-02-17 13:52:14 +01:00
change requests
This commit is contained in:
@@ -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 →",
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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)' },
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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);
|
||||
}, []);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
10
frontend/src/core/constants/downloads.ts
Normal file
10
frontend/src/core/constants/downloads.ts
Normal 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/';
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user