Move RenderSaveButton over

This commit is contained in:
Trevor Buckner
2026-09-14 21:08:04 +00:00
parent 13731f5771
commit 7c2344460f
4 changed files with 44 additions and 162 deletions
+2 -50
View File
@@ -53,8 +53,6 @@ const EditPage = (props)=>{
}; };
const [currentBrew, setCurrentBrew] = useState(props.brew); const [currentBrew, setCurrentBrew] = useState(props.brew);
const [isSaving, setIsSaving] = useState(false);
const [lastSavedTime, setLastSavedTime] = useState(new Date());
const [saveGoogle, setSaveGoogle] = useState(!!props.brew.googleId); const [saveGoogle, setSaveGoogle] = useState(!!props.brew.googleId);
const [error, setError] = useState(null); const [error, setError] = useState(null);
const [HTMLErrors, setHTMLErrors] = useState(hbfm.validate(props.brew.text)); const [HTMLErrors, setHTMLErrors] = useState(hbfm.validate(props.brew.text));
@@ -62,13 +60,10 @@ const EditPage = (props)=>{
const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1); const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1);
const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1);
const [themeBundle, setThemeBundle] = useState({}); const [themeBundle, setThemeBundle] = useState({});
const [unsavedChanges, setUnsavedChanges] = useState(false);
const [alertTrashedGoogleBrew, setAlertTrashedGoogleBrew] = useState(props.brew.trashed); const [alertTrashedGoogleBrew, setAlertTrashedGoogleBrew] = useState(props.brew.trashed);
const [alertNoGoogleToTransfer, setAlertNoGoogleToTransfer] = useState(false); const [alertNoGoogleToTransfer, setAlertNoGoogleToTransfer] = useState(false);
const [alertOwnershipToTransfer, setAlertOwnershipToTransfer] = useState(false); const [alertOwnershipToTransfer, setAlertOwnershipToTransfer] = useState(false);
const [confirmGoogleTransfer, setConfirmGoogleTransfer] = useState(false); const [confirmGoogleTransfer, setConfirmGoogleTransfer] = useState(false);
const [autoSaveEnabled, setAutoSaveEnabled] = useState(true);
const [warnUnsavedChanges, setWarnUnsavedChanges] = useState(true);
const editorRef = useRef(null); const editorRef = useRef(null);
const lastSavedBrew = useRef(_.cloneDeep(props.brew)); const lastSavedBrew = useRef(_.cloneDeep(props.brew));
@@ -206,41 +201,6 @@ const EditPage = (props)=>{
</Nav.item> </Nav.item>
); );
const renderSaveButton = ()=>{
// #1 - Currently saving, show SAVING
if(isSaving)
return <Nav.item className='save' icon='fas fa-spinner fa-spin'>saving...</Nav.item>;
// #2 - Unsaved changes exist, autosave is OFF and warning timer has expired, show AUTOSAVE WARNING
if(unsavedChanges && warnUnsavedChanges) {
resetWarnUnsavedTimer();
const elapsedTime = Math.round((new Date() - lastSavedTime) / 1000 / 60);
const text = elapsedTime === 0
? `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}.`
: `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}, and you haven't saved for ${elapsedTime} minutes.`;
return <Nav.item className='save error' icon='fas fa-exclamation-circle'>
Reminder...
<div className='errorContainer'>{text}</div>
</Nav.item>;
}
// #3 - Unsaved changes exist, click to save, show SAVE NOW
if(unsavedChanges)
return <Nav.item className='save' onClick={()=>trySave(true, true, saveGoogle)} color='blue' icon='fas fa-save'>save now</Nav.item>;
// #4 - No unsaved changes, autosave is ON, show AUTO-SAVED
if(autoSaveEnabled)
return <Nav.item className='save saved'>auto-saved</Nav.item>;
// #5 - Sandbox with no unsaved changes, and has never been saved, hide the button
if(sandbox)
return <Nav.item className='save sandbox' disabled={true}>save now</Nav.item>;
// DEFAULT - No unsaved changes, show SAVED
return <Nav.item className='save saved'>saved</Nav.item>;
};
const renderAutoSaveButton = ()=>( const renderAutoSaveButton = ()=>(
<Nav.item onClick={toggleAutoSave}> <Nav.item onClick={toggleAutoSave}>
Autosave <i className={autoSaveEnabled ? 'fas fa-power-off active' : 'fas fa-power-off'}></i> Autosave <i className={autoSaveEnabled ? 'fas fa-power-off active' : 'fas fa-power-off'}></i>
@@ -273,11 +233,12 @@ const EditPage = (props)=>{
}; };
const { const {
resetWarnUnsavedTimer,
handleSplitMove, handleSplitMove,
handleBrewChange, handleBrewChange,
toggleAutoSave, toggleAutoSave,
clearError, clearError,
renderSaveButton,
autoSaveEnabled,
trySave trySave
} = useCommonEditPageFunctions({ } = useCommonEditPageFunctions({
saveGoogle, saveGoogle,
@@ -293,19 +254,10 @@ const EditPage = (props)=>{
SNIPKEY, SNIPKEY,
METAKEY, METAKEY,
hbfm, hbfm,
autoSaveEnabled,
setAutoSaveEnabled,
setWarnUnsavedChanges,
unsavedChanges,
setUnsavedChanges,
sandbox, sandbox,
lastSavedBrew, lastSavedBrew,
editorRef, editorRef,
isSaving,
setIsSaving,
save, save,
lastSavedTime,
setLastSavedTime
}); });
return ( return (
+2 -50
View File
@@ -53,11 +53,6 @@ const HomePage =(props)=>{
const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1); const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1);
const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1);
const [themeBundle, setThemeBundle] = useState({}); const [themeBundle, setThemeBundle] = useState({});
const [unsavedChanges, setUnsavedChanges] = useState(false);
const [isSaving, setIsSaving] = useState(false);
const [lastSavedTime, setLastSavedTime] = useState(new Date());
const [autoSaveEnabled, setAutoSaveEnabled] = useState(false);
const [warnUnsavedChanges, setWarnUnsavedChanges] = useState(true);
const editorRef = useRef(null); const editorRef = useRef(null);
const lastSavedBrew = useRef(_.cloneDeep(props.brew)); const lastSavedBrew = useRef(_.cloneDeep(props.brew));
@@ -77,41 +72,6 @@ const HomePage =(props)=>{
window.location = `/edit/${saved.editId}`; window.location = `/edit/${saved.editId}`;
}; };
const renderSaveButton = ()=>{
// #1 - Currently saving, show SAVING
if(isSaving)
return <Nav.item className='save' icon='fas fa-spinner fa-spin'>saving...</Nav.item>;
// #2 - Unsaved changes exist, autosave is OFF and warning timer has expired, show AUTOSAVE WARNING
if(unsavedChanges && warnUnsavedChanges) {
resetWarnUnsavedTimer();
const elapsedTime = Math.round((new Date() - lastSavedTime) / 1000 / 60);
const text = elapsedTime === 0
? `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}.`
: `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}, and you haven't saved for ${elapsedTime} minutes.`;
return <Nav.item className='save error' icon='fas fa-exclamation-circle'>
Reminder...
<div className='errorContainer'>{text}</div>
</Nav.item>;
}
// #3 - Unsaved changes exist, click to save, show SAVE NOW
if(unsavedChanges)
return <Nav.item className='save' onClick={()=>trySave(true, true, saveGoogle)} color='blue' icon='fas fa-save'>save now</Nav.item>;
// #4 - No unsaved changes, autosave is ON, show AUTO-SAVED
if(autoSaveEnabled)
return <Nav.item className='save saved'>auto-saved</Nav.item>;
// #5 - Sandbox with no unsaved changes, and has never been saved, hide the button
if(sandbox)
return <Nav.item className='save neverSaved' disabled={true}>save now</Nav.item>;
// DEFAULT - No unsaved changes, show SAVED
return <Nav.item className='save saved'>saved</Nav.item>;
};
const renderNavbar = ()=>{ const renderNavbar = ()=>{
return <Navbar ver={props.ver}> return <Navbar ver={props.ver}>
<Nav.section> <Nav.section>
@@ -129,10 +89,11 @@ const HomePage =(props)=>{
}; };
const { const {
resetWarnUnsavedTimer,
handleSplitMove, handleSplitMove,
handleBrewChange, handleBrewChange,
clearError, clearError,
renderSaveButton,
unsavedChanges,
trySave trySave
} = useCommonEditPageFunctions({ } = useCommonEditPageFunctions({
saveGoogle, saveGoogle,
@@ -148,19 +109,10 @@ const HomePage =(props)=>{
SNIPKEY, SNIPKEY,
METAKEY, METAKEY,
hbfm, hbfm,
autoSaveEnabled,
setAutoSaveEnabled,
setWarnUnsavedChanges,
unsavedChanges,
setUnsavedChanges,
sandbox, sandbox,
lastSavedBrew, lastSavedBrew,
editorRef, editorRef,
isSaving,
setIsSaving,
save, save,
lastSavedTime,
setLastSavedTime
}); });
return ( return (
+1 -51
View File
@@ -45,8 +45,6 @@ const NewPage = (props)=>{
}; };
const [currentBrew, setCurrentBrew] = useState(props.brew); const [currentBrew, setCurrentBrew] = useState(props.brew);
const [isSaving, setIsSaving] = useState(false);
const [lastSavedTime, setLastSavedTime] = useState(new Date());
const [saveGoogle, setSaveGoogle] = useState(global.account?.googleId ? true : false); const [saveGoogle, setSaveGoogle] = useState(global.account?.googleId ? true : false);
const [error, setError] = useState(null); const [error, setError] = useState(null);
const [HTMLErrors, setHTMLErrors] = useState(hbfm.validate(props.brew.text)); const [HTMLErrors, setHTMLErrors] = useState(hbfm.validate(props.brew.text));
@@ -54,9 +52,6 @@ const NewPage = (props)=>{
const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1); const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1);
const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1);
const [themeBundle, setThemeBundle] = useState({}); const [themeBundle, setThemeBundle] = useState({});
const [unsavedChanges, setUnsavedChanges] = useState(false);
const [autoSaveEnabled, setAutoSaveEnabled] = useState(false);
const [warnUnsavedChanges, setWarnUnsavedChanges] = useState(true);
const editorRef = useRef(null); const editorRef = useRef(null);
const lastSavedBrew = useRef(_.cloneDeep(props.brew)); const lastSavedBrew = useRef(_.cloneDeep(props.brew));
@@ -121,41 +116,6 @@ const NewPage = (props)=>{
window.location = `/edit/${savedBrew.editId}`; window.location = `/edit/${savedBrew.editId}`;
}; };
const renderSaveButton = ()=>{
// #1 - Currently saving, show SAVING
if(isSaving)
return <Nav.item className='save' icon='fas fa-spinner fa-spin'>saving...</Nav.item>;
// #2 - Unsaved changes exist, autosave is OFF and warning timer has expired, show AUTOSAVE WARNING
if(unsavedChanges && warnUnsavedChanges) {
resetWarnUnsavedTimer();
const elapsedTime = Math.round((new Date() - lastSavedTime) / 1000 / 60);
const text = elapsedTime === 0
? `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}.`
: `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}, and you haven't saved for ${elapsedTime} minutes.`;
return <Nav.item className='save error' icon='fas fa-exclamation-circle'>
Reminder...
<div className='errorContainer'>{text}</div>
</Nav.item>;
}
// #3 - Unsaved changes exist, click to save, show SAVE NOW
if(unsavedChanges)
return <Nav.item className='save' onClick={()=>trySave(true, true, saveGoogle)} color='blue' icon='fas fa-save'>save now</Nav.item>;
// #4 - No unsaved changes, autosave is ON, show AUTO-SAVED
if(autoSaveEnabled)
return <Nav.item className='save saved'>auto-saved</Nav.item>;
// #5 - Sandbox with no unsaved changes, and has never been saved, hide the button
if(sandbox)
return <Nav.item className='save neverSaved' disabled={true}>save now</Nav.item>;
// DEFAULT - No unsaved changes, show SAVED
return <Nav.item className='save saved'>saved</Nav.item>;
};
const renderNavbar = ()=>( const renderNavbar = ()=>(
<Navbar> <Navbar>
<Nav.section> <Nav.section>
@@ -177,11 +137,10 @@ const NewPage = (props)=>{
); );
const { const {
resetWarnUnsavedTimer,
handleSplitMove, handleSplitMove,
handleBrewChange, handleBrewChange,
clearError, clearError,
trySave renderSaveButton
} = useCommonEditPageFunctions({ } = useCommonEditPageFunctions({
saveGoogle, saveGoogle,
setError, setError,
@@ -196,19 +155,10 @@ const NewPage = (props)=>{
SNIPKEY, SNIPKEY,
METAKEY, METAKEY,
hbfm, hbfm,
autoSaveEnabled,
setAutoSaveEnabled,
setWarnUnsavedChanges,
unsavedChanges,
setUnsavedChanges,
sandbox, sandbox,
lastSavedBrew, lastSavedBrew,
editorRef, editorRef,
isSaving,
setIsSaving,
save, save,
lastSavedTime,
setLastSavedTime
}); });
return ( return (
@@ -1,6 +1,7 @@
import React, { useState, useEffect, useEffectEvent, useRef } from 'react'; import React, { useState, useEffect, useEffectEvent, useRef } from 'react';
import { printCurrentBrew, fetchThemeBundle } from '@shared/helpers.js'; import { printCurrentBrew, fetchThemeBundle } from '@shared/helpers.js';
import _ from 'lodash'; import _ from 'lodash';
import Nav from '@navbar/nav.jsx';
const AUTOSAVE_KEY = 'HB_editor_autoSaveOn'; const AUTOSAVE_KEY = 'HB_editor_autoSaveOn';
@@ -23,21 +24,18 @@ export default function useCommonEditPageFunctions(dependencies) {
SNIPKEY, SNIPKEY,
METAKEY, METAKEY,
hbfm, hbfm,
autoSaveEnabled,
setAutoSaveEnabled,
setWarnUnsavedChanges,
sandbox, sandbox,
unsavedChanges,
setUnsavedChanges,
lastSavedBrew, lastSavedBrew,
editorRef, editorRef,
isSaving,
setIsSaving,
save, save,
lastSavedTime,
setLastSavedTime
} = dependencies; } = dependencies;
const [isSaving, setIsSaving] = useState(false);
const [lastSavedTime, setLastSavedTime] = useState(new Date());
const [autoSaveEnabled, setAutoSaveEnabled] = useState(!sandbox);
const [warnUnsavedChanges, setWarnUnsavedChanges] = useState(true);
const [unsavedChanges, setUnsavedChanges] = useState(false);
const unsavedChangesRef = useRef(unsavedChanges); // onBeforeUnload lives outside React and needs ref to unsavedChanges const unsavedChangesRef = useRef(unsavedChanges); // onBeforeUnload lives outside React and needs ref to unsavedChanges
const warnUnsavedTimeout = useRef(null); // timers live outside React and need ref to consistently track time const warnUnsavedTimeout = useRef(null); // timers live outside React and need ref to consistently track time
const saveTimeout = useRef(null); const saveTimeout = useRef(null);
@@ -59,7 +57,6 @@ export default function useCommonEditPageFunctions(dependencies) {
e.preventDefault(); e.preventDefault();
} }
}; };
document.addEventListener('keydown', handleControlKeys); document.addEventListener('keydown', handleControlKeys);
window.onbeforeunload = ()=>{ window.onbeforeunload = ()=>{
if(unsavedChangesRef.current) if(unsavedChangesRef.current)
@@ -145,12 +142,43 @@ export default function useCommonEditPageFunctions(dependencies) {
}, newTimeout); }, newTimeout);
}); });
const renderSaveButton = ()=>{
if(isSaving)
return <Nav.item className='save' icon='fas fa-spinner fa-spin'>saving...</Nav.item>;
if(unsavedChanges && warnUnsavedChanges) {
resetWarnUnsavedTimer();
const elapsedTime = Math.round((new Date() - lastSavedTime) / 1000 / 60);
const text = elapsedTime === 0
? `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}.`
: `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}, and you haven't saved for ${elapsedTime} minutes.`;
return <Nav.item className='save error' icon='fas fa-exclamation-circle'>
Reminder...
<div className='errorContainer'>{text}</div>
</Nav.item>;
}
if(unsavedChanges)
return <Nav.item className='save' onClick={()=>trySave(true, true, saveGoogle)} color='blue' icon='fas fa-save'>save now</Nav.item>;
if(autoSaveEnabled)
return <Nav.item className='save saved'>auto-saved</Nav.item>;
if(sandbox)
return <Nav.item className='save neverSaved' disabled={true}>save now</Nav.item>;
return <Nav.item className='save saved'>saved</Nav.item>;
};
return { return {
resetWarnUnsavedTimer,
handleSplitMove, handleSplitMove,
handleBrewChange, handleBrewChange,
toggleAutoSave, toggleAutoSave,
clearError, clearError,
trySave, trySave,
renderSaveButton,
autoSaveEnabled,
unsavedChanges,
} }
} }