mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-09-18 09:29:24 +00:00
Reset route on all tools
This commit is contained in:
parent
79c50f4bc5
commit
83400dc6a7
@ -144,12 +144,14 @@ export const NavigationProvider: React.FC<{
|
||||
|
||||
clearToolSelection: useCallback(() => {
|
||||
dispatch({ type: 'SET_SELECTED_TOOL', payload: { toolKey: null } });
|
||||
dispatch({ type: 'SET_MODE', payload: { mode: getDefaultMode() } });
|
||||
}, []),
|
||||
|
||||
handleToolSelect: useCallback((toolId: string) => {
|
||||
// Handle special cases
|
||||
if (toolId === 'allTools') {
|
||||
dispatch({ type: 'SET_SELECTED_TOOL', payload: { toolKey: null } });
|
||||
dispatch({ type: 'SET_MODE', payload: { mode: getDefaultMode() } });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,129 +0,0 @@
|
||||
// src/hooks/useToolUrlRouting.ts
|
||||
// Focused hook for URL <-> tool-key mapping and browser history sync.
|
||||
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
export interface UseToolUrlRoutingOpts {
|
||||
/** Currently selected tool key (from context). */
|
||||
selectedToolKey: string | null;
|
||||
/** Registry of available tools (key -> tool metadata). */
|
||||
toolRegistry: Record<string, any> | null | undefined;
|
||||
/** Select a tool (no extra side-effects). */
|
||||
selectTool: (toolKey: string) => void;
|
||||
/** Clear selection. */
|
||||
clearToolSelection: () => void;
|
||||
/** Called once during initialization if URL contains a tool; may trigger UI changes. */
|
||||
onInitSelect?: (toolKey: string) => void;
|
||||
/** Called when navigating via back/forward (popstate). Defaults to selectTool. */
|
||||
onPopStateSelect?: (toolKey: string) => void;
|
||||
/** Optional base path if the app isn't served at "/" (no trailing slash). Default: "" (root). */
|
||||
basePath?: string;
|
||||
}
|
||||
|
||||
export function useToolUrlRouting(opts: UseToolUrlRoutingOpts) {
|
||||
const {
|
||||
selectedToolKey,
|
||||
toolRegistry,
|
||||
selectTool,
|
||||
clearToolSelection,
|
||||
onInitSelect,
|
||||
onPopStateSelect,
|
||||
basePath = '',
|
||||
} = opts;
|
||||
|
||||
// Central slug map; keep here to co-locate routing policy.
|
||||
const urlMap = useMemo(
|
||||
() =>
|
||||
new Map<string, string>([
|
||||
['compress', 'compress-pdf'],
|
||||
['split', 'split-pdf'],
|
||||
['convert', 'convert-pdf'],
|
||||
['ocr', 'ocr-pdf'],
|
||||
['merge', 'merge-pdf'],
|
||||
['rotate', 'rotate-pdf'],
|
||||
]),
|
||||
[]
|
||||
);
|
||||
|
||||
const getToolUrlSlug = useCallback(
|
||||
(toolKey: string) => urlMap.get(toolKey) ?? toolKey,
|
||||
[urlMap]
|
||||
);
|
||||
|
||||
const getToolKeyFromSlug = useCallback(
|
||||
(slug: string) => {
|
||||
for (const [key, value] of urlMap) {
|
||||
if (value === slug) return key;
|
||||
}
|
||||
return slug; // fall back to raw key
|
||||
},
|
||||
[urlMap]
|
||||
);
|
||||
|
||||
// Internal flag to avoid clearing URL on initial mount.
|
||||
const [hasInitialized, setHasInitialized] = useState(false);
|
||||
|
||||
// Normalize a pathname by stripping basePath and leading slash.
|
||||
const normalizePath = useCallback(
|
||||
(fullPath: string) => {
|
||||
let p = fullPath;
|
||||
if (basePath && p.startsWith(basePath)) {
|
||||
p = p.slice(basePath.length);
|
||||
}
|
||||
if (p.startsWith('/')) p = p.slice(1);
|
||||
return p;
|
||||
},
|
||||
[basePath]
|
||||
);
|
||||
|
||||
// Update URL when tool changes (but not on first paint before any selection happens).
|
||||
useEffect(() => {
|
||||
if (selectedToolKey) {
|
||||
const slug = getToolUrlSlug(selectedToolKey);
|
||||
const newUrl = `${basePath}/${slug}`.replace(/\/+/, '/');
|
||||
window.history.replaceState({}, '', newUrl);
|
||||
setHasInitialized(true);
|
||||
} else if (hasInitialized) {
|
||||
const rootUrl = basePath || '/';
|
||||
window.history.replaceState({}, '', rootUrl);
|
||||
}
|
||||
}, [selectedToolKey, getToolUrlSlug, hasInitialized, basePath]);
|
||||
|
||||
// Initialize from URL when the registry is ready and nothing is selected yet.
|
||||
useEffect(() => {
|
||||
if (!toolRegistry || Object.keys(toolRegistry).length === 0) return;
|
||||
if (selectedToolKey) return; // don't override explicit selection
|
||||
|
||||
const currentPath = normalizePath(window.location.pathname);
|
||||
if (currentPath) {
|
||||
const toolKey = getToolKeyFromSlug(currentPath);
|
||||
if (toolRegistry[toolKey]) {
|
||||
(onInitSelect ?? selectTool)(toolKey);
|
||||
}
|
||||
}
|
||||
}, [toolRegistry, selectedToolKey, getToolKeyFromSlug, selectTool, onInitSelect, normalizePath]);
|
||||
|
||||
// Handle browser back/forward. NOTE: useRef needs an initial value in TS.
|
||||
const popHandlerRef = useRef<((this: Window, ev: PopStateEvent) => any) | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
popHandlerRef.current = () => {
|
||||
const path = normalizePath(window.location.pathname);
|
||||
if (path) {
|
||||
const toolKey = getToolKeyFromSlug(path);
|
||||
if (toolRegistry && toolRegistry[toolKey]) {
|
||||
(onPopStateSelect ?? selectTool)(toolKey);
|
||||
return;
|
||||
}
|
||||
}
|
||||
clearToolSelection();
|
||||
};
|
||||
|
||||
const handler = (e: PopStateEvent) => popHandlerRef.current?.call(window, e);
|
||||
window.addEventListener('popstate', handler);
|
||||
return () => window.removeEventListener('popstate', handler);
|
||||
}, [toolRegistry, selectTool, clearToolSelection, getToolKeyFromSlug, onPopStateSelect, normalizePath]);
|
||||
|
||||
// Expose pure helpers if you want them elsewhere (optional).
|
||||
return { getToolUrlSlug, getToolKeyFromSlug };
|
||||
}
|
@ -28,9 +28,9 @@ export function useNavigationUrlSync(
|
||||
useEffect(() => {
|
||||
if (!enableSync) return;
|
||||
|
||||
if (currentMode === 'pageEditor') {
|
||||
clearToolRoute();
|
||||
} else {
|
||||
// Only update URL for actual tool modes, not internal UI modes
|
||||
// URL clearing is handled by useToolWorkflowUrlSync when selectedToolKey becomes null
|
||||
if (currentMode !== 'fileEditor' && currentMode !== 'pageEditor' && currentMode !== 'viewer') {
|
||||
updateToolRoute(currentMode, currentMode);
|
||||
}
|
||||
}, [currentMode, enableSync]);
|
||||
@ -81,6 +81,9 @@ export function useToolWorkflowUrlSync(
|
||||
if (route.toolKey !== selectedToolKey) {
|
||||
updateToolRoute(selectedToolKey as ModeType, selectedToolKey);
|
||||
}
|
||||
} else {
|
||||
// Clear URL when no tool is selected - always clear regardless of current URL
|
||||
clearToolRoute();
|
||||
}
|
||||
}, [selectedToolKey, enableSync]);
|
||||
}
|
||||
|
@ -96,14 +96,20 @@ export function updateToolRoute(mode: ModeType, toolKey?: string): void {
|
||||
// Map modes to URL paths (only for actual tools)
|
||||
if (toolKey) {
|
||||
const pathMappings: Record<string, string> = {
|
||||
'split': '/split-pdf',
|
||||
'split': '/split-pdfs',
|
||||
'merge': '/merge-pdf',
|
||||
'compress': '/compress-pdf',
|
||||
'convert': '/convert-pdf',
|
||||
'addPassword': '/add-password-pdf',
|
||||
'changePermissions': '/change-permissions-pdf',
|
||||
'sanitize': '/sanitize-pdf',
|
||||
'ocr': '/ocr-pdf'
|
||||
'ocr': '/ocr-pdf',
|
||||
'addWatermark': '/watermark',
|
||||
'removePassword': '/remove-password',
|
||||
'single-large-page': '/single-large-page',
|
||||
'repair': '/repair',
|
||||
'unlockPdfForms': '/unlock-pdf-forms',
|
||||
'removeCertificateSign': '/remove-certificate-sign'
|
||||
};
|
||||
|
||||
newPath = pathMappings[toolKey] || `/${toolKey}`;
|
||||
@ -176,7 +182,13 @@ export function generateShareableUrl(mode: ModeType, toolKey?: string): string {
|
||||
'addPassword': '/add-password-pdf',
|
||||
'changePermissions': '/change-permissions-pdf',
|
||||
'sanitize': '/sanitize-pdf',
|
||||
'ocr': '/ocr-pdf'
|
||||
'ocr': '/ocr-pdf',
|
||||
'addWatermark': '/watermark',
|
||||
'removePassword': '/remove-password',
|
||||
'single-large-page': '/single-large-page',
|
||||
'repair': '/repair',
|
||||
'unlockPdfForms': '/unlock-pdf-forms',
|
||||
'removeCertificateSign': '/remove-certificate-sign'
|
||||
};
|
||||
|
||||
const path = pathMappings[toolKey] || `/${toolKey}`;
|
||||
|
Loading…
x
Reference in New Issue
Block a user