Merge pull request #811 from buster-so/big-nate-bus-1676-add-undo-redo

Big nate bus 1676 add undo redo
This commit is contained in:
Nate Kelley 2025-09-09 09:24:39 -06:00 committed by GitHub
commit 1dcd2c92d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 130 additions and 40 deletions

View File

@ -36,6 +36,7 @@ import { useBusterNotifications } from '@/context/BusterNotifications';
import { useGetChatId } from '@/context/Chats/useGetChatId';
import { useReportPageExport } from '@/context/Reports/useReportPageExport';
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
import { useIsMac } from '@/hooks/usePlatform';
import { useEditorContext } from '@/layouts/AssetContainer/ReportAssetContainer';
import { canEdit, getIsEffectiveOwner } from '@/lib/share';
@ -386,28 +387,41 @@ const useDownloadPdfSelectMenu = ({
};
const useUndoRedo = (): IDropdownItems => {
const { editor, setEditor } = useEditorContext();
return createDropdownItems([
{
label: 'Undo',
value: 'undo',
icon: <Undo />,
onClick: () => {
console.log('Undo');
console.log(editor);
// editor?.tf.undo();
},
},
{
label: 'Redo',
value: 'redo',
icon: <Redo />,
onClick: () => {
console.log('Redo');
// editor?.tf.redo();
},
},
]);
const { editor } = useEditorContext();
const isMac = useIsMac();
const getEditor = () => {
if (!editor?.current) {
console.warn('Editor is not defined');
return;
}
return editor?.current;
};
return useMemo(
() =>
createDropdownItems([
{
label: 'Undo',
value: 'undo',
shortcut: isMac ? '⌘+Z' : 'Ctrl+Z',
icon: <Undo />,
onClick: () => {
const editorInstance = getEditor();
editorInstance?.undo();
},
},
{
label: 'Redo',
value: 'redo',
shortcut: isMac ? '⌘+⇧+Z' : 'Ctrl+⇧+Z',
icon: <Redo />,
onClick: () => {
const editorInstance = getEditor();
editorInstance?.redo();
},
},
]),
[isMac]
);
};
const useDuplicateReportSelectMenu = ({ reportId }: { reportId: string }): IDropdownItem => {

View File

@ -0,0 +1,87 @@
import { useMemo } from 'react';
import { isServer } from '@/lib/window';
/**
* Hook to detect if the user is on a Mac system
* @returns {boolean} true if the user is on a Mac, false otherwise (Windows, Linux, etc.)
*/
export const useIsMac = (): boolean => {
return useMemo(() => {
if (isServer) {
return false; // Server-side rendering fallback
}
// Check the user agent for Mac indicators
const userAgent = window.navigator.userAgent.toLowerCase();
return userAgent.includes('macintosh') || userAgent.includes('mac os');
}, []);
};
/**
* Hook to detect if the user is on a Windows system
* @returns {boolean} true if the user is on Windows, false otherwise
*/
export const useIsWindows = (): boolean => {
return useMemo(() => {
if (isServer) {
return false; // Server-side rendering fallback
}
// Check the user agent for Windows indicators
const userAgent = window.navigator.userAgent.toLowerCase();
return userAgent.includes('windows');
}, []);
};
/**
* Hook to get the platform type
* @returns {'mac' | 'windows' | 'other'} the detected platform
*/
export const usePlatform = (): 'mac' | 'windows' | 'other' => {
return useMemo(() => {
if (typeof window === 'undefined') {
return 'other'; // Server-side rendering fallback
}
const userAgent = window.navigator.userAgent.toLowerCase();
if (userAgent.includes('macintosh') || userAgent.includes('mac os')) {
return 'mac';
}
if (userAgent.includes('windows')) {
return 'windows';
}
return 'other';
}, []);
};
export const useBrowser = (): 'chrome' | 'firefox' | 'safari' | 'edge' | 'other' => {
return useMemo(() => {
if (isServer) {
return 'other'; // Server-side rendering fallback
}
const userAgent = window.navigator.userAgent.toLowerCase();
if (userAgent.includes('chrome')) {
return 'chrome';
}
if (userAgent.includes('firefox')) {
return 'firefox';
}
if (userAgent.includes('safari')) {
return 'safari';
}
if (userAgent.includes('edge')) {
return 'edge';
}
return 'other';
}, []);
};

View File

@ -5,13 +5,8 @@ import { useMemoizedFn } from '@/hooks/useMemoizedFn';
const useReportAssetContext = () => {
const [forceUpdate, startForceUpdate] = useTransition();
const [hasEditor, setHasEditor] = useState(false);
const [versionHistoryMode, setVersionHistoryMode] = useState<number | false>(false);
const editor = useRef<BusterReportEditor | null>(null);
const undo = useRef<(() => void) | null>(null);
const redo = useRef<(() => void) | null>(null);
console.log('hasEditor', editor.current, !!undo.current, !!redo.current, hasEditor, forceUpdate);
const openReportVersionHistoryMode = useMemoizedFn((versionNumber: number) => {
setVersionHistoryMode(versionNumber);
@ -21,19 +16,13 @@ const useReportAssetContext = () => {
setVersionHistoryMode(false);
});
const setEditor = useMemoizedFn((editor: BusterReportEditor) => {
if (!editor) {
const setEditor = useMemoizedFn((editorInstance: BusterReportEditor) => {
if (!editorInstance) {
return;
}
editor.current = editor;
undo.current = editor.undo;
redo.current = editor.redo;
startForceUpdate(() => {
setHasEditor(true);
console.log('setEditor2', editor.current);
console.log('editor.current', editor.current);
editor.current = editorInstance;
});
});
@ -42,7 +31,7 @@ const useReportAssetContext = () => {
closeVersionHistoryMode,
versionHistoryMode,
setEditor,
hasEditor,
forceUpdate,
editor,
};
};
@ -84,13 +73,13 @@ export const useReportVersionHistoryMode = () => {
};
const stableSetEditorSelector = (x: ReturnType<typeof useReportAssetContext>) => x.setEditor;
const stableHasEditorSelector = (x: ReturnType<typeof useReportAssetContext>) => x.hasEditor;
const stableForceUpdateSelector = (x: ReturnType<typeof useReportAssetContext>) => x.forceUpdate;
export const useEditorContext = () => {
const hasEditor = useContextSelector(ReportAssetContext, stableHasEditorSelector);
const forceUpdate = useContextSelector(ReportAssetContext, stableForceUpdateSelector);
const setEditor = useContextSelector(ReportAssetContext, stableSetEditorSelector);
const editor = useContextSelector(
ReportAssetContext,
useCallback((x) => x.editor, [hasEditor])
useCallback((x) => x.editor, [forceUpdate])
);
if (!setEditor) {