From 3e2ac93424d248461cb82eef465c3db7815c6849 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sun, 13 Sep 2026 16:24:45 -0400 Subject: [PATCH] Make trySave common and move to useCommonEditorFunctions Also makes "save()" more common between the pages, but they still have some differences --- client/homebrew/pages/editPage/editPage.jsx | 32 ++++----------- client/homebrew/pages/homePage/homePage.jsx | 40 +++++++++++-------- client/homebrew/pages/newPage/newPage.jsx | 40 ++++++++++--------- .../homebrew/utils/commonEditPageFunctions.js | 35 +++++++++++++--- 4 files changed, 82 insertions(+), 65 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index b9dbe9dce..a0287236b 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -38,8 +38,6 @@ import LockNotification from './lockNotification/lockNotification.jsx'; import { updateHistory, versionHistoryGarbageCollection } from '../../utils/versionHistory.js'; import googleDriveIcon from '../../googleDrive.svg'; -const SAVE_TIMEOUT = 10000; - const BREWKEY = 'HB_newPage_content'; const STYLEKEY = 'HB_newPage_style'; const SNIPKEY = 'HB_newPage_snippets'; @@ -74,7 +72,6 @@ const EditPage = (props)=>{ const editorRef = useRef(null); const lastSavedBrew = useRef(_.cloneDeep(props.brew)); - const saveTimeout = useRef(null); const updateBrew = (newData)=>setCurrentBrew((prevBrew)=>({ ...prevBrew, @@ -113,25 +110,6 @@ const EditPage = (props)=>{ trySave(true, true, newSaveGoogle); }; - const trySave = useEffectEvent((immediate = false, hasChanges = true, saveToGoogle = false)=>{ - clearTimeout(saveTimeout.current); - if(isSaving) return; - if(!hasChanges && !immediate) return; - const newTimeout = immediate ? 0 : SAVE_TIMEOUT; - - saveTimeout.current = setTimeout(async ()=>{ - setIsSaving(true); - setError(null); - await save(currentBrew, saveToGoogle) - .catch((err)=>{ - setError(err); - }); - setIsSaving(false); - setLastSavedTime(new Date()); - if(!autoSaveEnabled) resetWarnUnsavedTimer(); - }, newTimeout); - }); - const save = async (brew, saveToGoogle)=>{ setHTMLErrors(hbfm.validate(brew.text)); @@ -303,7 +281,8 @@ const EditPage = (props)=>{ resetWarnUnsavedTimer, handleSplitMove, handleBrewChange, - toggleAutoSave + toggleAutoSave, + trySave } = useCommonEditPageFunctions({ saveGoogle, setError, @@ -323,11 +302,14 @@ const EditPage = (props)=>{ setWarnUnsavedChanges, unsavedChanges, setUnsavedChanges, - trySave, sandbox, lastSavedBrew, editorRef, - saveTimeout + isSaving, + setIsSaving, + save, + lastSavedTime, + setLastSavedTime }); return ( diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index 7685f7bc5..a1a4a257e 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -31,8 +31,6 @@ const { both: RecentNavItem } = RecentNavItems; import Headtags from '@vitreum/headtags.js'; const Meta = Headtags.Meta; -const SAVE_TIMEOUT = 10000; - const BREWKEY = 'HB_newPage_content'; const STYLEKEY = 'HB_newPage_style'; const SNIPKEY = 'HB_newPage_snippets'; @@ -48,6 +46,7 @@ const HomePage =(props)=>{ }; const [currentBrew, setCurrentBrew] = useState(props.brew); + const [saveGoogle, setSaveGoogle] = useState(global.account?.googleId ? true : false); const [error, setError] = useState(undefined); const [HTMLErrors, setHTMLErrors] = useState(hbfm.validate(props.brew.text)); const [currentEditorViewPageNum, setCurrentEditorViewPageNum] = useState(1); @@ -63,17 +62,19 @@ const HomePage =(props)=>{ const editorRef = useRef(null); const lastSavedBrew = useRef(_.cloneDeep(props.brew)); - const save = ()=>{ - request.post('/api') - .send(currentBrew) - .end((err, res)=>{ - if(err) { - setError(err); - return; - } - const saved = res.body; - window.location = `/edit/${saved.editId}`; + const save = async (brew, saveToGoogle)=>{ + const res = await request + .post(`/api${saveGoogle ? '?saveToGoogle=true' : ''}`) + .send(brew) + .catch((err)=>{ + console.error('Error Updating Local Brew'); + setError(err); }); + if(!res) return; + + const saved = res.body; + window.onbeforeunload = null; + window.location = `/edit/${saved.editId}`; }; const renderSaveButton = ()=>{ @@ -97,7 +98,7 @@ const HomePage =(props)=>{ // #3 - Unsaved changes exist, click to save, show SAVE NOW if(unsavedChanges) - return save now; + return trySave(true, true, saveGoogle)} color='blue' icon='fas fa-save'>save now; // #4 - No unsaved changes, autosave is ON, show AUTO-SAVED if(autoSaveEnabled) @@ -135,8 +136,10 @@ const HomePage =(props)=>{ const { resetWarnUnsavedTimer, handleSplitMove, - handleBrewChange + handleBrewChange, + trySave } = useCommonEditPageFunctions({ + saveGoogle, setError, setThemeBundle, HTMLErrors, @@ -156,7 +159,12 @@ const HomePage =(props)=>{ setUnsavedChanges, sandbox, lastSavedBrew, - editorRef + editorRef, + isSaving, + setIsSaving, + save, + lastSavedTime, + setLastSavedTime }); return ( @@ -190,7 +198,7 @@ const HomePage =(props)=>{ /> -
+
trySave(true, true, saveGoogle)}> Save current
diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index 9db9f11f2..1ec1720f4 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -28,8 +28,6 @@ import RecentNavItems from '@navbar/recent.navitem.jsx'; const { both: RecentNavItem } = RecentNavItems; // Page specific imports -const SAVE_TIMEOUT = 10000; - const BREWKEY = 'HB_newPage_content'; const STYLEKEY = 'HB_newPage_style'; const SNIPKEY = 'HB_newPage_snippets'; @@ -96,24 +94,22 @@ const NewPage = (props)=>{ window.history.replaceState({}, window.location.title, '/new/'); }; - const trySave = useEffectEvent(async ()=>{ - setIsSaving(true); - - const updatedBrew = { ...currentBrew }; - splitTextStyleAndMetadata(updatedBrew); - - const pageRegex = updatedBrew.renderer === 'legacy' ? /\\page/g : /^(?=\\page(?:break)?(?: *{[^\n{}]*})?$)/gm; - updatedBrew.pageCount = (updatedBrew.text.match(pageRegex) || []).length + 1; + const save = async (brew, saveToGoogle)=>{ + //Prepare content to send to server + const brewToSave = { + ...brew, + text : brew.text.normalize('NFC'), + pageCount : ((brew.renderer === 'legacy' ? brew.text.match(/\\page/g) : brew.text.match(/^(?=\\page(?:break)?(?: *{[^\n{}]*})?$)/gm)) || []).length + 1, + textBin : undefined + }; const res = await request .post(`/api${saveGoogle ? '?saveToGoogle=true' : ''}`) - .send(updatedBrew) + .send(brewToSave) .catch((err)=>{ - setIsSaving(false); + console.error('Error Updating Local Brew'); setError(err); }); - - setIsSaving(false); if(!res) return; const savedBrew = res.body; @@ -123,7 +119,7 @@ const NewPage = (props)=>{ localStorage.removeItem(METAKEY); window.onbeforeunload = null; window.location = `/edit/${savedBrew.editId}`; - }); + }; const renderSaveButton = ()=>{ // #1 - Currently saving, show SAVING @@ -146,7 +142,7 @@ const NewPage = (props)=>{ // #3 - Unsaved changes exist, click to save, show SAVE NOW if(unsavedChanges) - return save now; + return trySave(true, true, saveGoogle)} color='blue' icon='fas fa-save'>save now; // #4 - No unsaved changes, autosave is ON, show AUTO-SAVED if(autoSaveEnabled) @@ -188,8 +184,10 @@ const NewPage = (props)=>{ const { resetWarnUnsavedTimer, handleSplitMove, - handleBrewChange + handleBrewChange, + trySave } = useCommonEditPageFunctions({ + saveGoogle, setError, setThemeBundle, HTMLErrors, @@ -207,10 +205,14 @@ const NewPage = (props)=>{ setWarnUnsavedChanges, unsavedChanges, setUnsavedChanges, - trySave, sandbox, lastSavedBrew, - editorRef + editorRef, + isSaving, + setIsSaving, + save, + lastSavedTime, + setLastSavedTime }); return ( diff --git a/client/homebrew/utils/commonEditPageFunctions.js b/client/homebrew/utils/commonEditPageFunctions.js index f0c398ae4..e49e29136 100644 --- a/client/homebrew/utils/commonEditPageFunctions.js +++ b/client/homebrew/utils/commonEditPageFunctions.js @@ -1,14 +1,16 @@ -import React, { useState, useEffect, useRef } from 'react'; +import React, { useState, useEffect, useEffectEvent, useRef } from 'react'; import { printCurrentBrew, fetchThemeBundle } from '@shared/helpers.js'; import _ from 'lodash'; const AUTOSAVE_KEY = 'HB_editor_autoSaveOn'; +const SAVE_TIMEOUT = 10000; //Autosave 10 seconds after last change const UNSAVED_WARNING_TIMEOUT = 900000; //Warn user afer 15 minutes of unsaved changes const UNSAVED_WARNING_POPUP_TIMEOUT = 4000; //Show the warning for 4 seconds export default function useCommonEditPageFunctions(dependencies) { const { + saveGoogle, setError, setThemeBundle, HTMLErrors, @@ -24,18 +26,21 @@ export default function useCommonEditPageFunctions(dependencies) { autoSaveEnabled, setAutoSaveEnabled, setWarnUnsavedChanges, - trySave = ()=>{}, sandbox, - saveGoogle = false, unsavedChanges, setUnsavedChanges, lastSavedBrew, editorRef, - saveTimeout = undefined + isSaving, + setIsSaving, + save, + lastSavedTime, + setLastSavedTime } = dependencies; 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 saveTimeout = useRef(null); //==--------- Page setup ----------==// useEffect(()=>{ @@ -116,10 +121,30 @@ export default function useCommonEditPageFunctions(dependencies) { setWarnUnsavedChanges(autoSaveEnabled); }; + const trySave = useEffectEvent((forceSave = false, hasChanges = true, saveToGoogle = false)=>{ + clearTimeout(saveTimeout.current); + if(isSaving) return; + if(!forceSave && !hasChanges) return; + const newTimeout = forceSave ? 0 : SAVE_TIMEOUT; + + saveTimeout.current = setTimeout(async ()=>{ + setIsSaving(true); + setError(null); + await save(currentBrew, saveToGoogle) + .catch((err)=>{ + setError(err); + }); + setIsSaving(false); + setLastSavedTime(new Date()); + if(!autoSaveEnabled) resetWarnUnsavedTimer(); + }, newTimeout); + }); + return { resetWarnUnsavedTimer, handleSplitMove, handleBrewChange, - toggleAutoSave + toggleAutoSave, + trySave, } } \ No newline at end of file