Merge pull request #5009 from naturalcrit/new/edit/home-exctractcommonsetupsteps

New/Edit/Home Move setup effects to common functions
This commit is contained in:
Trevor Buckner
2026-09-11 22:41:05 -04:00
committed by GitHub
4 changed files with 104 additions and 137 deletions
+9 -34
View File
@@ -8,7 +8,6 @@ import { hbfm } from 'hbmarkedwrapper';
import _ from 'lodash'; import _ from 'lodash';
import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js'; import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js';
import { printCurrentBrew, fetchThemeBundle } from '@shared/helpers.js';
import useCommonEditPageFunctions from '../../utils/commonEditPageFunctions.js' import useCommonEditPageFunctions from '../../utils/commonEditPageFunctions.js'
@@ -43,7 +42,6 @@ const SAVE_TIMEOUT = 10000;
const UNSAVED_WARNING_TIMEOUT = 900000; //Warn user afer 15 minutes of unsaved changes 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 const UNSAVED_WARNING_POPUP_TIMEOUT = 4000; //Show the warning for 4 seconds
const AUTOSAVE_KEY = 'HB_editor_autoSaveOn';
const BREWKEY = 'HB_newPage_content'; const BREWKEY = 'HB_newPage_content';
const STYLEKEY = 'HB_newPage_style'; const STYLEKEY = 'HB_newPage_style';
const SNIPKEY = 'HB_newPage_snippets'; const SNIPKEY = 'HB_newPage_snippets';
@@ -90,46 +88,23 @@ const EditPage = (props)=>{
setThemeBundle, setThemeBundle,
HTMLErrors, HTMLErrors,
setHTMLErrors, setHTMLErrors,
currentBrew,
setCurrentBrew, setCurrentBrew,
useLocalStorage, useLocalStorage,
BREWKEY, BREWKEY,
STYLEKEY, STYLEKEY,
SNIPKEY, SNIPKEY,
METAKEY, METAKEY,
fetchThemeBundle, hbfm,
hbfm autoSaveEnabled,
setAutoSaveEnabled,
setWarnUnsavedChanges,
trySaveRef,
unsavedChangesRef,
sandbox,
saveGoogle
}); });
useEffect(()=>{
const autoSavePref = !sandbox && JSON.parse(localStorage.getItem(AUTOSAVE_KEY) ?? true);
setAutoSaveEnabled(autoSavePref);
setWarnUnsavedChanges(!autoSavePref);
setHTMLErrors(hbfm.validate(currentBrew.text));
fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme);
const handleControlKeys = (e)=>{
if(!(e.ctrlKey || e.metaKey)) return;
if(e.keyCode === 83) trySaveRef.current(true, true, saveGoogle);
if(e.keyCode === 80) printCurrentBrew();
if([83, 80].includes(e.keyCode)) {
e.stopPropagation();
e.preventDefault();
}
};
document.addEventListener('keydown', handleControlKeys);
window.onbeforeunload = ()=>{
if(unsavedChangesRef.current)
return 'You have unsaved changes!';
};
return ()=>{
document.removeEventListener('keydown', handleControlKeys);
window.onbeforeunload = null;
};
}, []);
useEffect(()=>{ useEffect(()=>{
trySaveRef.current = trySave; trySaveRef.current = trySave;
unsavedChangesRef.current = unsavedChanges; unsavedChangesRef.current = unsavedChanges;
+9 -34
View File
@@ -8,7 +8,6 @@ import { hbfm } from 'hbmarkedwrapper';
import _ from 'lodash'; import _ from 'lodash';
import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; import { DEFAULT_BREW } from '../../../../server/brewDefaults.js';
import { printCurrentBrew, fetchThemeBundle } from '@shared/helpers.js';
import useCommonEditPageFunctions from '../../utils/commonEditPageFunctions.js' import useCommonEditPageFunctions from '../../utils/commonEditPageFunctions.js'
@@ -36,7 +35,6 @@ const SAVE_TIMEOUT = 10000;
const UNSAVED_WARNING_TIMEOUT = 900000; //Warn user afer 15 minutes of unsaved changes 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 const UNSAVED_WARNING_POPUP_TIMEOUT = 4000; //Show the warning for 4 seconds
const AUTOSAVE_KEY = 'HB_editor_autoSaveOn';
const BREWKEY = 'HB_newPage_content'; const BREWKEY = 'HB_newPage_content';
const STYLEKEY = 'HB_newPage_style'; const STYLEKEY = 'HB_newPage_style';
const SNIPKEY = 'HB_newPage_snippets'; const SNIPKEY = 'HB_newPage_snippets';
@@ -67,6 +65,7 @@ const HomePage =(props)=>{
const editorRef = useRef(null); const editorRef = useRef(null);
const lastSavedBrew = useRef(_.cloneDeep(props.brew)); const lastSavedBrew = useRef(_.cloneDeep(props.brew));
const warnUnsavedTimeout = useRef(null); const warnUnsavedTimeout = useRef(null);
const trySaveRef = useRef(null); // CTRL+S listener lives outside React and needs ref to use trySave with latest copy of brew
const unsavedChangesRef = useRef(unsavedChanges); const unsavedChangesRef = useRef(unsavedChanges);
const { const {
@@ -76,46 +75,22 @@ const HomePage =(props)=>{
setThemeBundle, setThemeBundle,
HTMLErrors, HTMLErrors,
setHTMLErrors, setHTMLErrors,
currentBrew,
setCurrentBrew, setCurrentBrew,
useLocalStorage, useLocalStorage,
BREWKEY, BREWKEY,
STYLEKEY, STYLEKEY,
SNIPKEY, SNIPKEY,
METAKEY, METAKEY,
fetchThemeBundle, hbfm,
hbfm autoSaveEnabled,
setAutoSaveEnabled,
setWarnUnsavedChanges,
trySaveRef,
unsavedChangesRef,
sandbox
}); });
useEffect(()=>{
const autoSavePref = !sandbox && JSON.parse(localStorage.getItem(AUTOSAVE_KEY) ?? true);
setAutoSaveEnabled(autoSavePref);
setWarnUnsavedChanges(!autoSavePref);
setHTMLErrors(hbfm.validate(currentBrew.text));
fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme);
const handleControlKeys = (e)=>{
if(!(e.ctrlKey || e.metaKey)) return;
if(e.keyCode === 83) trySaveRef.current(true);
if(e.keyCode === 80) printCurrentBrew();
if([83, 80].includes(e.keyCode)) {
e.stopPropagation();
e.preventDefault();
}
};
document.addEventListener('keydown', handleControlKeys);
window.onbeforeunload = ()=>{
if(unsavedChangesRef.current)
return 'You have unsaved changes!';
};
return ()=>{
document.removeEventListener('keydown', handleControlKeys);
window.onbeforeunload = null;
};
}, []);
useEffect(()=>{ useEffect(()=>{
unsavedChangesRef.current = unsavedChanges; unsavedChangesRef.current = unsavedChanges;
}, [unsavedChanges]); }, [unsavedChanges]);
+8 -33
View File
@@ -32,7 +32,6 @@ const SAVE_TIMEOUT = 10000;
const UNSAVED_WARNING_TIMEOUT = 900000; //Warn user afer 15 minutes of unsaved changes 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 const UNSAVED_WARNING_POPUP_TIMEOUT = 4000; //Show the warning for 4 seconds
const AUTOSAVE_KEY = 'HB_editor_autoSaveOn';
const BREWKEY = 'HB_newPage_content'; const BREWKEY = 'HB_newPage_content';
const STYLEKEY = 'HB_newPage_style'; const STYLEKEY = 'HB_newPage_style';
const SNIPKEY = 'HB_newPage_snippets'; const SNIPKEY = 'HB_newPage_snippets';
@@ -81,46 +80,22 @@ const NewPage = (props)=>{
setThemeBundle, setThemeBundle,
HTMLErrors, HTMLErrors,
setHTMLErrors, setHTMLErrors,
currentBrew,
setCurrentBrew, setCurrentBrew,
useLocalStorage, useLocalStorage,
BREWKEY, BREWKEY,
STYLEKEY, STYLEKEY,
SNIPKEY, SNIPKEY,
METAKEY, METAKEY,
fetchThemeBundle, hbfm,
hbfm autoSaveEnabled,
setAutoSaveEnabled,
setWarnUnsavedChanges,
trySaveRef,
unsavedChangesRef,
sandbox
}); });
useEffect(()=>{
const autoSavePref = !sandbox && JSON.parse(localStorage.getItem(AUTOSAVE_KEY) ?? true);
setAutoSaveEnabled(autoSavePref);
setWarnUnsavedChanges(!autoSavePref);
setHTMLErrors(hbfm.validate(currentBrew.text));
fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme);
const handleControlKeys = (e)=>{
if(!(e.ctrlKey || e.metaKey)) return;
if(e.keyCode === 83) trySaveRef.current(true);
if(e.keyCode === 80) printCurrentBrew();
if([83, 80].includes(e.keyCode)) {
e.stopPropagation();
e.preventDefault();
}
};
document.addEventListener('keydown', handleControlKeys);
window.onbeforeunload = ()=>{
if(unsavedChangesRef.current)
return 'You have unsaved changes!';
};
return ()=>{
document.removeEventListener('keydown', handleControlKeys);
window.onbeforeunload = null;
};
}, []);
const loadBrew = ()=>{ const loadBrew = ()=>{
const brew = { ...currentBrew }; const brew = { ...currentBrew };
if(!brew.shareId && typeof window !== 'undefined') { //Load from localStorage if in client browser if(!brew.shareId && typeof window !== 'undefined') { //Load from localStorage if in client browser
@@ -1,43 +1,85 @@
import React, { useState, useEffect, useRef } from 'react';
import { printCurrentBrew, fetchThemeBundle } from '@shared/helpers.js';
const AUTOSAVE_KEY = 'HB_editor_autoSaveOn';
export default function useCommonEditPageFunctions(dependencies) { export default function useCommonEditPageFunctions(dependencies) {
const { const {
setError, setError,
setThemeBundle, setThemeBundle,
HTMLErrors, HTMLErrors,
setHTMLErrors, setHTMLErrors,
setCurrentBrew, currentBrew,
useLocalStorage, setCurrentBrew,
BREWKEY, useLocalStorage,
STYLEKEY, BREWKEY,
SNIPKEY, STYLEKEY,
METAKEY, SNIPKEY,
fetchThemeBundle, METAKEY,
hbfm hbfm,
} = dependencies; autoSaveEnabled,
setAutoSaveEnabled,
setWarnUnsavedChanges,
trySaveRef,
sandbox,
saveGoogle = false,
unsavedChangesRef
} = dependencies;
const handleBrewChange = (field)=>(value, subfield)=>{ //'text', 'style', 'snippets', 'metadata' //==--------- Page setup ----------==//
if(subfield == 'renderer' || subfield == 'theme') useEffect(()=>{
fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); const autoSavePref = !sandbox && JSON.parse(localStorage.getItem(AUTOSAVE_KEY) ?? true);
setAutoSaveEnabled(autoSavePref);
console.log(autoSavePref)
setWarnUnsavedChanges(!autoSavePref);
setHTMLErrors(hbfm.validate(currentBrew.text));
fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme);
//If there are HTML errors, run the validator on every change to give quick feedback const handleControlKeys = (e)=>{
if(HTMLErrors.length && (field == 'text' || field == 'snippets')) if(!(e.ctrlKey || e.metaKey)) return;
setHTMLErrors(hbfm.validate(value)); if(e.keyCode === 83) trySaveRef.current(true, true, saveGoogle);
if(e.keyCode === 80) printCurrentBrew();
if([83, 80].includes(e.keyCode)) {
e.stopPropagation();
e.preventDefault();
}
};
if(field == 'metadata') setCurrentBrew((prev)=>({ ...prev, ...value })); document.addEventListener('keydown', handleControlKeys);
else setCurrentBrew((prev)=>({ ...prev, [field]: value })); window.onbeforeunload = ()=>{
if(unsavedChangesRef.current)
return 'You have unsaved changes!';
};
return ()=>{
document.removeEventListener('keydown', handleControlKeys);
window.onBeforeUnload = null;
};
}, []);
if(useLocalStorage) { const handleBrewChange = (field)=>(value, subfield)=>{ //'text', 'style', 'snippets', 'metadata'
if(field == 'text') localStorage.setItem(BREWKEY, value); if(subfield == 'renderer' || subfield == 'theme')
if(field == 'style') localStorage.setItem(STYLEKEY, value); fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme);
if(field == 'snippets') localStorage.setItem(SNIPKEY, value);
if(field == 'metadata') localStorage.setItem(METAKEY, JSON.stringify({
renderer : value.renderer,
theme : value.theme,
lang : value.lang
}));
}
};
return { //If there are HTML errors, run the validator on every change to give quick feedback
handleBrewChange if(HTMLErrors.length && (field == 'text' || field == 'snippets'))
} setHTMLErrors(hbfm.validate(value));
if(field == 'metadata') setCurrentBrew((prev)=>({ ...prev, ...value }));
else setCurrentBrew((prev)=>({ ...prev, [field]: value }));
if(useLocalStorage) {
if(field == 'text') localStorage.setItem(BREWKEY, value);
if(field == 'style') localStorage.setItem(STYLEKEY, value);
if(field == 'snippets') localStorage.setItem(SNIPKEY, value);
if(field == 'metadata') localStorage.setItem(METAKEY, JSON.stringify({
renderer : value.renderer,
theme : value.theme,
lang : value.lang
}));
}
};
return {
handleBrewChange
}
} }