From 077aaeb815d78ee4bb4bb2c873a62d6b6389efc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 27 May 2025 10:54:07 +0200 Subject: [PATCH 01/20] log --- client/homebrew/brewRenderer/brewRenderer.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index c391d8c43..4b65a9425 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -290,6 +290,7 @@ const BrewRenderer = (props)=>{ const styleObject = {}; + console.log(global.config); if(global.config.deployment) { styleObject.backgroundImage = `url("data:image/svg+xml;utf8,${global.config.deployment}")`; } From ed05d8c754d6a76a65076f4cb6a1d78e0aca53f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 27 May 2025 11:25:01 +0200 Subject: [PATCH 02/20] move all to homebrew.jsx --- client/homebrew/brewRenderer/brewRenderer.jsx | 10 +------ .../homebrew/brewRenderer/brewRenderer.less | 1 - client/homebrew/homebrew.jsx | 27 +++++++++++++++++-- client/homebrew/homebrew.less | 4 ++- .../homebrew/pages/vaultPage/vaultPage.less | 7 ++--- 5 files changed, 33 insertions(+), 16 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 4b65a9425..82c1ebb19 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -288,13 +288,6 @@ const BrewRenderer = (props)=>{ rowGap : `${displayOptions.rowGap}px` }; - const styleObject = {}; - - console.log(global.config); - if(global.config.deployment) { - styleObject.backgroundImage = `url("data:image/svg+xml;utf8,${global.config.deployment}")`; - } - const renderedStyle = useMemo(()=>renderStyle(), [props.style, props.themeBundle]); renderedPages = useMemo(()=>renderPages(), [props.text, displayOptions]); @@ -323,10 +316,9 @@ const BrewRenderer = (props)=>{ contentDidMount={frameDidMount} onClick={()=>{emitClick();}} > -
{/* Apply CSS from Style tab and render pages from Markdown tab */} diff --git a/client/homebrew/brewRenderer/brewRenderer.less b/client/homebrew/brewRenderer/brewRenderer.less index b0a3e9779..bb4fe69c5 100644 --- a/client/homebrew/brewRenderer/brewRenderer.less +++ b/client/homebrew/brewRenderer/brewRenderer.less @@ -6,7 +6,6 @@ overflow-y : scroll; will-change : transform; &:has(.facing, .flow) { padding : 60px 30px; } - &.deployment { background-color : darkred; } :where(.pages) { &.facing { display : grid; diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index 415390498..6e7a95a31 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -63,13 +63,36 @@ const Homebrew = createClass({ global.enable_themes = this.props.enable_themes; global.config = this.props.config; - return {}; + return { isClient: false }; }, + componentDidMount : function() { + this.setState({ isClient: true }); + }, + + backgroundObject : function() { + if(!this.state.isClient) return null; + + if(this.props.config.deployment) { + return { + backgroundImage : `url("data:image/svg+xml;utf8,${this.props.config.deployment}")` + }; + } else if(this.props.config.local) { + return { + backgroundImage : `url("data:image/svg+xml;utf8,Local")` + }; + } + + return null; + }, + + render : function (){ return ( -
+
} /> } /> diff --git a/client/homebrew/homebrew.less b/client/homebrew/homebrew.less index e265c2941..6df5254ec 100644 --- a/client/homebrew/homebrew.less +++ b/client/homebrew/homebrew.less @@ -1,12 +1,14 @@ @import 'naturalcrit/styles/core.less'; .homebrew { height : 100%; + &.deployment { background-color : darkred; } + .sitePage { display : flex; flex-direction : column; height : 100%; overflow-y : hidden; - background-color : @steel; + //background-color : @steel; .content { position : relative; flex : auto; diff --git a/client/homebrew/pages/vaultPage/vaultPage.less b/client/homebrew/pages/vaultPage/vaultPage.less index 8a5f3a714..304fefc72 100644 --- a/client/homebrew/pages/vaultPage/vaultPage.less +++ b/client/homebrew/pages/vaultPage/vaultPage.less @@ -1,14 +1,16 @@ .vaultPage { height : 100%; overflow-y : hidden; - background-color : #2C3E50; *:not(input) { user-select : none; } + .form { + background:white; + } + :where(.content .dataGroup) { width : 100%; height : 100%; - background : white; &.form .brewLookup { position : relative; @@ -171,7 +173,6 @@ max-height : 100%; padding : 70px 50px; overflow-y : scroll; - background-color : #2C3E50; container-type : inline-size; h3 { font-size : 25px; } From 88b70d340e6fccb2e21176e254d9211bd9051a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 27 May 2025 11:27:04 +0200 Subject: [PATCH 03/20] final bit --- client/homebrew/homebrew.less | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/homebrew.less b/client/homebrew/homebrew.less index 6df5254ec..5c7b63023 100644 --- a/client/homebrew/homebrew.less +++ b/client/homebrew/homebrew.less @@ -1,6 +1,7 @@ @import 'naturalcrit/styles/core.less'; .homebrew { height : 100%; + background-color:@steel; &.deployment { background-color : darkred; } .sitePage { From f04d6cdd1fd245569aa1ecc5db7598c42d8cfa2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 17 Jul 2025 23:32:18 +0200 Subject: [PATCH 04/20] fix to current --- client/homebrew/homebrew.jsx | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index a6b4b9175..a261e76ef 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -1,7 +1,7 @@ /* eslint-disable camelcase */ import 'core-js/es/string/to-well-formed.js'; //Polyfill for older browsers import './homebrew.less'; -import React from 'react'; +import { useState, useEffect } from 'react'; import { StaticRouter as Router, Route, Routes, useParams, useSearchParams } from 'react-router'; import HomePage from './pages/homePage/homePage.jsx'; @@ -17,7 +17,6 @@ const WithRoute = ({ el: Element, ...rest })=>{ const params = useParams(); const [searchParams] = useSearchParams(); const queryParams = Object.fromEntries(searchParams?.entries() || []); - return ; }; @@ -42,15 +41,35 @@ const Homebrew = (props)=>{ brews } = props; + const [isClient, setIsClient] = useState(false); + + useEffect(() => { + setIsClient(true); + }, []); + global.account = account; global.version = version; global.enable_v3 = enable_v3; global.enable_themes = enable_themes; global.config = config; + const backgroundObject = ()=>{ + if(!isClient) return null; + if(config.deployment) { + return { + backgroundImage : `url("data:image/svg+xml;utf8,${config.deployment}")` + }; + } else if(config.local) { + return { + backgroundImage : `url("data:image/svg+xml;utf8,Local")` + }; + } + return null; + }; + return ( -
+
} /> } /> @@ -72,4 +91,4 @@ const Homebrew = (props)=>{ ); }; -module.exports = Homebrew; \ No newline at end of file +module.exports = Homebrew; From d6a5a1f03c82025f10e0862a2cb261c0b25be8f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 18 Jul 2025 00:39:36 +0200 Subject: [PATCH 05/20] no idea what changed but now it works --- client/homebrew/homebrew.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index a261e76ef..095c679f1 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -1,7 +1,7 @@ /* eslint-disable camelcase */ import 'core-js/es/string/to-well-formed.js'; //Polyfill for older browsers import './homebrew.less'; -import { useState, useEffect } from 'react'; +import React, { useState, useEffect } from 'react'; import { StaticRouter as Router, Route, Routes, useParams, useSearchParams } from 'react-router'; import HomePage from './pages/homePage/homePage.jsx'; @@ -43,7 +43,7 @@ const Homebrew = (props)=>{ const [isClient, setIsClient] = useState(false); - useEffect(() => { + useEffect(()=>{ setIsClient(true); }, []); From da8772daa7e3f417bb0dc4b8a4a673ccc3973e79 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Thu, 11 Sep 2025 16:14:45 -0400 Subject: [PATCH 06/20] Use setXXXPageNum instead of handleXXXPageNum No need for separate wrapper functions when we can just pass the setState functions directly. --- client/homebrew/pages/editPage/editPage.jsx | 18 +++--------------- client/homebrew/pages/homePage/homePage.jsx | 18 +++--------------- client/homebrew/pages/newPage/newPage.jsx | 17 +++-------------- 3 files changed, 9 insertions(+), 44 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 49512d66c..1467a2a89 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -111,18 +111,6 @@ const EditPage = (props)=>{ editorRef.current?.update(); }; - const handleEditorViewPageChange = (pageNumber)=>{ - setCurrentEditorViewPageNum(pageNumber); - }; - - const handleEditorCursorPageChange = (pageNumber)=>{ - setCurrentEditorCursorPageNum(pageNumber); - }; - - const handleBrewRendererPageChange = (pageNumber)=>{ - setCurrentBrewRendererPageNum(pageNumber); - }; - const handleTextChange = (text)=>{ //If there are HTML errors, run the validator on every change to give quick feedback if(HTMLErrors.length) @@ -417,8 +405,8 @@ const EditPage = (props)=>{ userThemes={props.userThemes} themeBundle={themeBundle} updateBrew={updateBrew} - onCursorPageChange={handleEditorCursorPageChange} - onViewPageChange={handleEditorViewPageChange} + onCursorPageChange={setCurrentEditorCursorPageNum} + onViewPageChange={setCurrentEditorViewPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} @@ -431,7 +419,7 @@ const EditPage = (props)=>{ themeBundle={themeBundle} errors={HTMLErrors} lang={currentBrew.lang} - onPageChange={handleBrewRendererPageChange} + onPageChange={setCurrentBrewRendererPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index 84967b1ff..f9713e13a 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -60,18 +60,6 @@ const HomePage =(props)=>{ editorRef.current.update(); }; - const handleEditorViewPageChange = (pageNumber)=>{ - setCurrentEditorViewPageNum(pageNumber); - }; - - const handleEditorCursorPageChange = (pageNumber)=>{ - setCurrentEditorCursorPageNum(pageNumber); - }; - - const handleBrewRendererPageChange = (pageNumber)=>{ - setCurrentBrewRendererPageNum(pageNumber); - }; - const handleTextChange = (text)=>{ setBrew((prevBrew) => ({ ...prevBrew, text })); }; @@ -110,8 +98,8 @@ const HomePage =(props)=>{ renderer={brew.renderer} showEditButtons={false} themeBundle={themeBundle} - onCursorPageChange={handleEditorCursorPageChange} - onViewPageChange={handleEditorViewPageChange} + onCursorPageChange={setCurrentEditorCursorPageNum} + onViewPageChange={setCurrentEditorViewPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} @@ -120,7 +108,7 @@ const HomePage =(props)=>{ text={brew.text} style={brew.style} renderer={brew.renderer} - onPageChange={handleBrewRendererPageChange} + onPageChange={setCurrentBrewRendererPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index bb21441cf..5c8853ec7 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -96,17 +96,6 @@ const NewPage = (props) => { editorRef.current.update(); }; - const handleEditorViewPageChange = (pageNumber)=>{ - setCurrentEditorViewPageNum(pageNumber); - }; - - const handleEditorCursorPageChange = (pageNumber)=>{ - setCurrentEditorCursorPageNum(pageNumber); - }; - - const handleBrewRendererPageChange = (pageNumber)=>{ - setCurrentBrewRendererPageNum(pageNumber); - }; const handleTextChange = (text)=>{ //If there are HTML errors, run the validator on every change to give quick feedback @@ -222,8 +211,8 @@ const NewPage = (props) => { renderer={currentBrew.renderer} userThemes={props.userThemes} themeBundle={themeBundle} - onCursorPageChange={handleEditorCursorPageChange} - onViewPageChange={handleEditorViewPageChange} + onCursorPageChange={setCurrentEditorCursorPageNum} + onViewPageChange={setCurrentEditorViewPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} @@ -236,7 +225,7 @@ const NewPage = (props) => { themeBundle={themeBundle} errors={HTMLErrors} lang={currentBrew.lang} - onPageChange={handleBrewRendererPageChange} + onPageChange={setCurrentBrewRendererPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} From 788324fe31b9cc4cc61155e9cad10bc6fef5d69d Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Thu, 11 Sep 2025 22:03:25 -0400 Subject: [PATCH 07/20] Merge handText/Style/Snip/MetaChange into handleBrewChange --- client/homebrew/editor/editor.jsx | 13 ++--- client/homebrew/pages/editPage/editPage.jsx | 47 ++++++++--------- client/homebrew/pages/homePage/homePage.jsx | 47 ++++++++++++----- client/homebrew/pages/newPage/newPage.jsx | 56 ++++++++------------- 4 files changed, 83 insertions(+), 80 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 8d331e46e..6558bd330 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -40,10 +40,7 @@ const Editor = createClass({ style : '' }, - onTextChange : ()=>{}, - onStyleChange : ()=>{}, - onMetaChange : ()=>{}, - onSnipChange : ()=>{}, + onBrewChange : ()=>{}, reportError : ()=>{}, onCursorPageChange : ()=>{}, @@ -438,7 +435,7 @@ const Editor = createClass({ language='gfm' view={this.state.view} value={this.props.brew.text} - onChange={this.props.onTextChange} + onChange={this.props.onBrewChange('text')} editorTheme={this.state.editorTheme} rerenderParent={this.rerenderParent} style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} /> @@ -451,7 +448,7 @@ const Editor = createClass({ language='css' view={this.state.view} value={this.props.brew.style ?? DEFAULT_STYLE_TEXT} - onChange={this.props.onStyleChange} + onChange={this.props.onBrewChange('style')} enableFolding={true} editorTheme={this.state.editorTheme} rerenderParent={this.rerenderParent} @@ -467,7 +464,7 @@ const Editor = createClass({ ; @@ -481,7 +478,7 @@ const Editor = createClass({ language='gfm' view={this.state.view} value={this.props.brew.snippets} - onChange={this.props.onSnipChange} + onChange={this.props.onBrewChange('snippets')} enableFolding={true} editorTheme={this.state.editorTheme} rerenderParent={this.rerenderParent} diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 1467a2a89..715ae72f9 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -1,7 +1,7 @@ /* eslint-disable max-lines */ import './editPage.less'; -import React, { useState, useEffect, useRef, useCallback } from 'react'; +import React, { useState, useEffect, useRef, useCallback, use } from 'react'; import request from '../../utils/request-middleware.js'; import Markdown from 'naturalcrit/markdown.js'; @@ -38,6 +38,8 @@ const SAVE_TIMEOUT = 10000; 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 useLocalStorage = false; + const EditPage = (props)=>{ props = { brew : DEFAULT_BREW_LOAD, @@ -111,29 +113,27 @@ const EditPage = (props)=>{ editorRef.current?.update(); }; - const handleTextChange = (text)=>{ + const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' + if (subfield == 'renderer' || subfield == 'theme') + fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); + //If there are HTML errors, run the validator on every change to give quick feedback - if(HTMLErrors.length) - setHTMLErrors(Markdown.validate(text)); - setCurrentBrew((prevBrew)=>({ ...prevBrew, text })); - }; + if(HTMLErrors.length && (field == 'text' || field == 'snippets')) + setHTMLErrors(Markdown.validate(value)); - const handleStyleChange = (style)=>{ - setCurrentBrew((prevBrew)=>({ ...prevBrew, style })); - }; + if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value })); + else setCurrentBrew(prev => ({ ...prev, [field]: value })); - const handleSnipChange = (snippet)=>{ - //If there are HTML errors, run the validator on every change to give quick feedback - if(HTMLErrors.length) - setHTMLErrors(Markdown.validate(snippet)); - setCurrentBrew((prevBrew)=>({ ...prevBrew, snippets: snippet })); - }; - - const handleMetaChange = (metadata, field = undefined)=>{ - if(field === 'theme' || field === 'renderer') - fetchThemeBundle(setError, setThemeBundle, metadata.renderer, metadata.theme); - - setCurrentBrew((prev)=>({ ...prev, ...metadata })); + 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 + })); + } }; const updateBrew = (newData)=>setCurrentBrew((prevBrew)=>({ @@ -396,10 +396,7 @@ const EditPage = (props)=>{ { props = { brew : DEFAULT_BREW, @@ -28,9 +31,10 @@ const HomePage =(props)=>{ ...props }; - const [brew , setBrew] = useState(props.brew); + const [currentBrew , setCurrentBrew] = useState(props.brew); const [welcomeText , setWelcomeText] = useState(props.brew.text); const [error , setError] = useState(undefined); + const [HTMLErrors , setHTMLErrors] = useState(Markdown.validate(props.brew.text)); const [currentEditorViewPageNum , setCurrentEditorViewPageNum] = useState(1); const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1); const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); @@ -40,12 +44,12 @@ const HomePage =(props)=>{ const editorRef = useRef(null); useEffect(()=>{ - fetchThemeBundle(setError, setThemeBundle, brew.renderer, brew.theme); + fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme); }, []); const save = ()=>{ request.post('/api') - .send(brew) + .send(currentBrew) .end((err, res)=>{ if(err) { setError(err); @@ -60,8 +64,27 @@ const HomePage =(props)=>{ editorRef.current.update(); }; - const handleTextChange = (text)=>{ - setBrew((prevBrew) => ({ ...prevBrew, text })); + const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' + if (subfield == 'renderer' || subfield == 'theme') + fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); + + //If there are HTML errors, run the validator on every change to give quick feedback + if(HTMLErrors.length && (field == 'text' || field == 'snippets')) + setHTMLErrors(Markdown.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 + })); + } }; const clearError = ()=>{ @@ -93,9 +116,9 @@ const HomePage =(props)=>{ { currentBrewRendererPageNum={currentBrewRendererPageNum} /> { />
-
+
Save current
diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index 5c8853ec7..60b8b17f0 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -22,9 +22,12 @@ import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '. const BREWKEY = 'homebrewery-new'; const STYLEKEY = 'homebrewery-new-style'; +const SNIPKEY = 'homebrewery-new-snippets'; const METAKEY = 'homebrewery-new-meta'; const SAVEKEY = `HOMEBREWERY-DEFAULT-SAVE-LOCATION-${global.account?.username || ''}`; +const useLocalStorage = true; + const NewPage = (props) => { props = { brew: DEFAULT_BREW, @@ -96,41 +99,27 @@ const NewPage = (props) => { editorRef.current.update(); }; + const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' + if (subfield == 'renderer' || subfield == 'theme') + fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); - const handleTextChange = (text)=>{ //If there are HTML errors, run the validator on every change to give quick feedback - if(HTMLErrors.length) - HTMLErrors = Markdown.validate(text); + if(HTMLErrors.length && (field == 'text' || field == 'snippets')) + setHTMLErrors(Markdown.validate(value)); - setHTMLErrors(HTMLErrors); - setCurrentBrew((prevBrew) => ({ ...prevBrew, text })); - localStorage.setItem(BREWKEY, text); - }; + if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value })); + else setCurrentBrew(prev => ({ ...prev, [field]: value })); - const handleStyleChange = (style) => { - setCurrentBrew(prevBrew => ({ ...prevBrew, style })); - localStorage.setItem(STYLEKEY, style); - }; - - const handleSnipChange = (snippet)=>{ - //If there are HTML errors, run the validator on every change to give quick feedback - if(HTMLErrors.length) - HTMLErrors = Markdown.validate(snippet); - - setHTMLErrors(HTMLErrors); - setCurrentBrew((prevBrew) => ({ ...prevBrew, snippets: snippet })); - }; - - const handleMetaChange = (metadata, field = undefined) => { - if (field === 'theme' || field === 'renderer') - fetchThemeBundle(setError, setThemeBundle, metadata.renderer, metadata.theme); - - setCurrentBrew(prev => ({ ...prev, ...metadata })); - localStorage.setItem(METAKEY, JSON.stringify({ - renderer : metadata.renderer, - theme : metadata.theme, - lang : metadata.lang - })); + 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 + })); + } }; const save = async () => { @@ -204,10 +193,7 @@ const NewPage = (props) => { Date: Mon, 29 Sep 2025 12:48:25 -0400 Subject: [PATCH 08/20] Make Print/Vault/New common nav buttons to all pages --- client/homebrew/pages/editPage/editPage.jsx | 36 ++++++------- client/homebrew/pages/homePage/homePage.jsx | 57 ++++++++++++++------- client/homebrew/pages/newPage/newPage.jsx | 53 ++++++++++--------- 3 files changed, 87 insertions(+), 59 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index af39838cf..c42032534 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -1,38 +1,38 @@ /* eslint-disable max-lines */ import './editPage.less'; -import React, { useState, useEffect, useRef, useCallback, use } from 'react'; +// Common imports +import React, { useState, useEffect, useRef } from 'react'; import request from '../../utils/request-middleware.js'; import Markdown from 'naturalcrit/markdown.js'; -import _ from 'lodash';; -import { makePatches, stringifyPatches } from '@sanity/diff-match-patch'; -import { md5 } from 'hash-wasm'; -import { gzipSync, strToU8 } from 'fflate'; -import { Meta } from 'vitreum/headtags'; +import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js'; +import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; + +import SplitPane from 'client/components/splitPane/splitPane.jsx'; +import Editor from '../../editor/editor.jsx'; +import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; import Nav from 'naturalcrit/nav/nav.jsx'; import Navbar from '../../navbar/navbar.jsx'; import NewBrewItem from '../../navbar/newbrew.navitem.jsx'; import AccountNavItem from '../../navbar/account.navitem.jsx'; -import ShareNavItem from '../../navbar/share.navitem.jsx'; import ErrorNavItem from '../../navbar/error-navitem.jsx'; import HelpNavItem from '../../navbar/help.navitem.jsx'; import VaultNavItem from '../../navbar/vault.navitem.jsx'; import PrintNavItem from '../../navbar/print.navitem.jsx'; import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; -import SplitPane from 'client/components/splitPane/splitPane.jsx'; -import Editor from '../../editor/editor.jsx'; -import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; +// Page specific imports +import { Meta } from 'vitreum/headtags'; +import _ from 'lodash'; +import { md5 } from 'hash-wasm'; +import { gzipSync, strToU8 } from 'fflate'; +import { makePatches, stringifyPatches } from '@sanity/diff-match-patch'; +import ShareNavItem from '../../navbar/share.navitem.jsx'; import LockNotification from './lockNotification/lockNotification.jsx'; - -import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js'; -import { printCurrentBrew, fetchThemeBundle } from '../../../../shared/helpers.js'; - import { updateHistory, versionHistoryGarbageCollection } from '../../utils/versionHistory.js'; - import googleDriveIcon from '../../googleDrive.svg'; const SAVE_TIMEOUT = 10000; @@ -344,11 +344,11 @@ const EditPage = (props)=>{ {renderSaveButton()} {renderAutoSaveButton()} } - - - + + + diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index c6625cade..b568e0ad0 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -1,26 +1,30 @@ +/* eslint-disable max-lines */ import './homePage.less'; -import React from 'react'; -import { useEffect, useState, useRef } from 'react'; -import request from '../../utils/request-middleware.js'; -import Markdown from 'naturalcrit/markdown.js'; -import { Meta } from 'vitreum/headtags'; +// Common imports +import React, { useState, useEffect, useRef } from 'react'; +import request from '../../utils/request-middleware.js'; +import Markdown from 'naturalcrit/markdown.js'; -import Nav from 'naturalcrit/nav/nav.jsx'; -import Navbar from '../../navbar/navbar.jsx'; -import NewBrewItem from '../../navbar/newbrew.navitem.jsx'; -import HelpNavItem from '../../navbar/help.navitem.jsx'; -import VaultNavItem from '../../navbar/vault.navitem.jsx'; -import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; -import AccountNavItem from '../../navbar/account.navitem.jsx'; -import ErrorNavItem from '../../navbar/error-navitem.jsx'; -import { fetchThemeBundle } from '../../../../shared/helpers.js'; +import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; +import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; -import SplitPane from 'client/components/splitPane/splitPane.jsx'; -import Editor from '../../editor/editor.jsx'; -import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; +import SplitPane from 'client/components/splitPane/splitPane.jsx'; +import Editor from '../../editor/editor.jsx'; +import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; -import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; +import Nav from 'naturalcrit/nav/nav.jsx'; +import Navbar from '../../navbar/navbar.jsx'; +import NewBrewItem from '../../navbar/newbrew.navitem.jsx'; +import AccountNavItem from '../../navbar/account.navitem.jsx'; +import ErrorNavItem from '../../navbar/error-navitem.jsx'; +import HelpNavItem from '../../navbar/help.navitem.jsx'; +import VaultNavItem from '../../navbar/vault.navitem.jsx'; +import PrintNavItem from '../../navbar/print.navitem.jsx'; +import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; + +// Page specific imports +import { Meta } from 'vitreum/headtags'; const useLocalStorage = false; @@ -45,6 +49,22 @@ const HomePage =(props)=>{ useEffect(()=>{ 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); + + return () => { + document.removeEventListener('keydown', handleControlKeys); + }; }, []); const save = ()=>{ @@ -100,6 +120,7 @@ const HomePage =(props)=>{ null } + diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index 60b8b17f0..6dd19dec6 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -1,24 +1,30 @@ -/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/ +/* eslint-disable max-lines */ import './newPage.less'; +// Common imports import React, { useState, useEffect, useRef } from 'react'; import request from '../../utils/request-middleware.js'; import Markdown from 'naturalcrit/markdown.js'; -import Nav from 'naturalcrit/nav/nav.jsx'; -import Navbar from '../../navbar/navbar.jsx'; -import AccountNavItem from '../../navbar/account.navitem.jsx'; -import ErrorNavItem from '../../navbar/error-navitem.jsx'; -import HelpNavItem from '../../navbar/help.navitem.jsx'; -import PrintNavItem from '../../navbar/print.navitem.jsx'; -import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; +import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; +import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; import SplitPane from 'client/components/splitPane/splitPane.jsx'; import Editor from '../../editor/editor.jsx'; import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; -import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; -import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; +import Nav from 'naturalcrit/nav/nav.jsx'; +import Navbar from '../../navbar/navbar.jsx'; +import NewBrewItem from '../../navbar/newbrew.navitem.jsx'; +import AccountNavItem from '../../navbar/account.navitem.jsx'; +import ErrorNavItem from '../../navbar/error-navitem.jsx'; +import HelpNavItem from '../../navbar/help.navitem.jsx'; +import VaultNavItem from '../../navbar/vault.navitem.jsx'; +import PrintNavItem from '../../navbar/print.navitem.jsx'; +import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; + +// Page specific imports +import { Meta } from 'vitreum/headtags'; const BREWKEY = 'homebrewery-new'; const STYLEKEY = 'homebrewery-new-style'; @@ -47,10 +53,21 @@ const NewPage = (props) => { const editorRef = useRef(null); useEffect(() => { - document.addEventListener('keydown', handleControlKeys); loadBrew(); 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); + return () => { document.removeEventListener('keydown', handleControlKeys); }; @@ -83,18 +100,6 @@ const NewPage = (props) => { window.history.replaceState({}, window.location.title, '/new/'); }; - const handleControlKeys = (e) => { - if (!(e.ctrlKey || e.metaKey)) return; - const S_KEY = 83; - const P_KEY = 80; - if (e.keyCode === S_KEY) save(); - if (e.keyCode === P_KEY) printCurrentBrew(); - if (e.keyCode === S_KEY || e.keyCode === P_KEY) { - e.preventDefault(); - e.stopPropagation(); - } - }; - const handleSplitMove = ()=>{ editorRef.current.update(); }; @@ -177,8 +182,10 @@ const NewPage = (props) => { {error ? : renderSaveButton()} + + From e793db7b37756c5ec0bc690602520e3e2fc49ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 1 Oct 2025 22:55:32 +0200 Subject: [PATCH 09/20] separating the words to make it less ugly --- client/homebrew/homebrew.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index 095c679f1..c1b3f7a96 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -57,11 +57,11 @@ const Homebrew = (props)=>{ if(!isClient) return null; if(config.deployment) { return { - backgroundImage : `url("data:image/svg+xml;utf8,${config.deployment}")` + backgroundImage : `url("data:image/svg+xml;utf8,${config.deployment}")` }; } else if(config.local) { return { - backgroundImage : `url("data:image/svg+xml;utf8,Local")` + backgroundImage : `url("data:image/svg+xml;utf8,Local")` }; } return null; From eefda9fe45687ab0006c2345bca1ba11e257b166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 2 Oct 2025 12:40:12 +0200 Subject: [PATCH 10/20] simplifying per suggestion --- client/homebrew/homebrew.jsx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index c1b3f7a96..933971c04 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -55,14 +55,11 @@ const Homebrew = (props)=>{ const backgroundObject = ()=>{ if(!isClient) return null; - if(config.deployment) { - return { - backgroundImage : `url("data:image/svg+xml;utf8,${config.deployment}")` - }; - } else if(config.local) { - return { - backgroundImage : `url("data:image/svg+xml;utf8,Local")` - }; + if(config.deployment || config.local){ + const bgText = config.deployment || 'Local'; + return { + backgroundImage : `url("data:image/svg+xml;utf8,${bgText}")` + }; } return null; }; From c2e51b0baa1257378b1e7fc22cca68ee7bc55c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 3 Oct 2025 21:32:52 +0200 Subject: [PATCH 11/20] removing isclient check to see what's what --- client/homebrew/homebrew.jsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index 933971c04..c85351289 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -41,12 +41,6 @@ const Homebrew = (props)=>{ brews } = props; - const [isClient, setIsClient] = useState(false); - - useEffect(()=>{ - setIsClient(true); - }, []); - global.account = account; global.version = version; global.enable_v3 = enable_v3; @@ -54,7 +48,6 @@ const Homebrew = (props)=>{ global.config = config; const backgroundObject = ()=>{ - if(!isClient) return null; if(config.deployment || config.local){ const bgText = config.deployment || 'Local'; return { @@ -66,7 +59,7 @@ const Homebrew = (props)=>{ return ( -
+
} /> } /> From e0379a0baa75c45b9479620164d53b47ce629e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 3 Oct 2025 21:38:10 +0200 Subject: [PATCH 12/20] last cleanup --- client/homebrew/homebrew.jsx | 2 +- client/homebrew/homebrew.less | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index c85351289..efdf70b49 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -1,7 +1,7 @@ /* eslint-disable camelcase */ import 'core-js/es/string/to-well-formed.js'; //Polyfill for older browsers import './homebrew.less'; -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { StaticRouter as Router, Route, Routes, useParams, useSearchParams } from 'react-router'; import HomePage from './pages/homePage/homePage.jsx'; diff --git a/client/homebrew/homebrew.less b/client/homebrew/homebrew.less index 5c7b63023..2cbc35857 100644 --- a/client/homebrew/homebrew.less +++ b/client/homebrew/homebrew.less @@ -9,7 +9,6 @@ flex-direction : column; height : 100%; overflow-y : hidden; - //background-color : @steel; .content { position : relative; flex : auto; From aff9a8576976cd5714ce02d811dff80605de8c1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 3 Oct 2025 21:38:43 +0200 Subject: [PATCH 13/20] end of file character shit --- client/homebrew/homebrew.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index efdf70b49..cfc691407 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -81,4 +81,4 @@ const Homebrew = (props)=>{ ); }; -module.exports = Homebrew; +module.exports = Homebrew; \ No newline at end of file From ae51213c8c428a27242c5e5b8acb0af4b4564528 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 5 Oct 2025 12:25:51 +1300 Subject: [PATCH 14/20] Permanently enable old local storage key deletion --- .../utils/updateLocalStorage/updateLocalStorageKeys.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js index 6d0bf0c8c..1a8231f73 100644 --- a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js +++ b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js @@ -10,15 +10,13 @@ const updateLocalStorage = function(){ const storage = window.localStorage; - const deleteKeys = storage?.getItem('HB_deleteKeys') != null; - Object.keys(localStorageKeyMap).forEach((key)=>{ if(storage[key]){ if(!storage[localStorageKeyMap[key]]){ const data = storage.getItem(key); storage.setItem(localStorageKeyMap[key], data); }; - if(deleteKeys) storage.removeItem(key); + storage.removeItem(key); } }); From 20e12ebcb5f759a28d279c65355492fa8793b2fd Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 4 Oct 2025 21:39:24 -0400 Subject: [PATCH 15/20] Remove handler function for cursor/renderer page. Use setState directly --- client/homebrew/pages/editPage/editPage.jsx | 18 +++--------------- client/homebrew/pages/homePage/homePage.jsx | 18 +++--------------- client/homebrew/pages/newPage/newPage.jsx | 18 +++--------------- 3 files changed, 9 insertions(+), 45 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 200a754c2..499cbb454 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -123,18 +123,6 @@ const EditPage = (props)=>{ editorRef.current?.update(); }; - const handleEditorViewPageChange = (pageNumber)=>{ - setCurrentEditorViewPageNum(pageNumber); - }; - - const handleEditorCursorPageChange = (pageNumber)=>{ - setCurrentEditorCursorPageNum(pageNumber); - }; - - const handleBrewRendererPageChange = (pageNumber)=>{ - setCurrentBrewRendererPageNum(pageNumber); - }; - const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' if (subfield == 'renderer' || subfield == 'theme') fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); @@ -394,8 +382,8 @@ const EditPage = (props)=>{ userThemes={props.userThemes} themeBundle={themeBundle} updateBrew={updateBrew} - onCursorPageChange={handleEditorCursorPageChange} - onViewPageChange={handleEditorViewPageChange} + onCursorPageChange={setCurrentEditorCursorPageNum} + onViewPageChange={setCurrentEditorViewPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} @@ -408,7 +396,7 @@ const EditPage = (props)=>{ themeBundle={themeBundle} errors={HTMLErrors} lang={currentBrew.lang} - onPageChange={handleBrewRendererPageChange} + onPageChange={setCurrentBrewRendererPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index 16811576e..0a4920b81 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -69,18 +69,6 @@ const HomePage =(props)=>{ editorRef.current.update(); }; - const handleEditorViewPageChange = (pageNumber)=>{ - setCurrentEditorViewPageNum(pageNumber); - }; - - const handleEditorCursorPageChange = (pageNumber)=>{ - setCurrentEditorCursorPageNum(pageNumber); - }; - - const handleBrewRendererPageChange = (pageNumber)=>{ - setCurrentBrewRendererPageNum(pageNumber); - }; - const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' if (subfield == 'renderer' || subfield == 'theme') fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); @@ -138,8 +126,8 @@ const HomePage =(props)=>{ renderer={currentBrew.renderer} showEditButtons={false} themeBundle={themeBundle} - onCursorPageChange={handleEditorCursorPageChange} - onViewPageChange={handleEditorViewPageChange} + onCursorPageChange={setCurrentEditorCursorPageNum} + onViewPageChange={setCurrentEditorViewPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} @@ -148,7 +136,7 @@ const HomePage =(props)=>{ text={currentBrew.text} style={currentBrew.style} renderer={currentBrew.renderer} - onPageChange={handleBrewRendererPageChange} + onPageChange={setCurrentBrewRendererPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index b8c4e8100..580a7a764 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -102,18 +102,6 @@ const NewPage = (props) => { editorRef.current.update(); }; - const handleEditorViewPageChange = (pageNumber)=>{ - setCurrentEditorViewPageNum(pageNumber); - }; - - const handleEditorCursorPageChange = (pageNumber)=>{ - setCurrentEditorCursorPageNum(pageNumber); - }; - - const handleBrewRendererPageChange = (pageNumber)=>{ - setCurrentBrewRendererPageNum(pageNumber); - }; - const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' if (subfield == 'renderer' || subfield == 'theme') fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); @@ -212,8 +200,8 @@ const NewPage = (props) => { renderer={currentBrew.renderer} userThemes={props.userThemes} themeBundle={themeBundle} - onCursorPageChange={handleEditorCursorPageChange} - onViewPageChange={handleEditorViewPageChange} + onCursorPageChange={setCurrentEditorCursorPageNum} + onViewPageChange={setCurrentEditorViewPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} @@ -226,7 +214,7 @@ const NewPage = (props) => { themeBundle={themeBundle} errors={HTMLErrors} lang={currentBrew.lang} - onPageChange={handleBrewRendererPageChange} + onPageChange={setCurrentBrewRendererPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} From 2c4c4b8f924c9e8626935751bfabd057cac4206b Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 4 Oct 2025 22:17:24 -0400 Subject: [PATCH 16/20] Make `unsavedChanges` state common /editPage.jsx uses `unsavedChanges` state to detect when autosave should fire, or unsaved changes warning should display. /homePage.jsx uses a similar check (different variables) to detect when to show the popup "save now"! button /newPage.jsx doesn't do any of this, but probably should pop up a warning when saving hasn't happened for a long time This commit just gives all of the pages the same common `unsavedChanges` state, calculated in the same way, and updates any sections that depend on that updated state. This is precursor work to adding "unsaved changes" warnings to all three pages. --- client/homebrew/pages/editPage/editPage.jsx | 2 +- client/homebrew/pages/homePage/homePage.jsx | 16 +++++++++++++--- client/homebrew/pages/newPage/newPage.jsx | 14 ++++++++++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index e3d449a55..3bd74b786 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -5,6 +5,7 @@ import './editPage.less'; import React, { useState, useEffect, useRef } from 'react'; import request from '../../utils/request-middleware.js'; import Markdown from 'naturalcrit/markdown.js'; +import _ from 'lodash'; import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js'; import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; @@ -25,7 +26,6 @@ import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; // Page specific imports import { Meta } from 'vitreum/headtags'; -import _ from 'lodash'; import { md5 } from 'hash-wasm'; import { gzipSync, strToU8 } from 'fflate'; import { makePatches, stringifyPatches } from '@sanity/diff-match-patch'; diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index fdc439ab5..cfa6eb59d 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -5,6 +5,7 @@ import './homePage.less'; import React, { useState, useEffect, useRef } from 'react'; import request from '../../utils/request-middleware.js'; import Markdown from 'naturalcrit/markdown.js'; +import _ from 'lodash'; import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; @@ -41,16 +42,18 @@ const HomePage =(props)=>{ }; const [currentBrew , setCurrentBrew] = useState(props.brew); - const [welcomeText , setWelcomeText] = useState(props.brew.text); const [error , setError] = useState(undefined); const [HTMLErrors , setHTMLErrors] = useState(Markdown.validate(props.brew.text)); const [currentEditorViewPageNum , setCurrentEditorViewPageNum] = useState(1); const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1); const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); const [themeBundle , setThemeBundle] = useState({}); + const [unsavedChanges , setUnsavedChanges] = useState(false); const [isSaving , setIsSaving] = useState(false); + const [autoSaveEnabled , setAutoSaveEnable] = useState(false); - const editorRef = useRef(null); + const editorRef = useRef(null); + const lastSavedBrew = useRef(_.cloneDeep(props.brew)); useEffect(()=>{ fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme); @@ -85,6 +88,13 @@ const HomePage =(props)=>{ }); }; + useEffect(()=>{ + const hasChange = !_.isEqual(currentBrew, lastSavedBrew.current); + setUnsavedChanges(hasChange); + + if(autoSaveEnabled) trySave(false, hasChange); + }, [currentBrew]); + const handleSplitMove = ()=>{ editorRef.current.update(); }; @@ -165,7 +175,7 @@ const HomePage =(props)=>{ />
-
+
Save current
diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index d1d1fa75c..b9b628a2c 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -5,6 +5,7 @@ import './newPage.less'; import React, { useState, useEffect, useRef } from 'react'; import request from '../../utils/request-middleware.js'; import Markdown from 'naturalcrit/markdown.js'; +import _ from 'lodash'; import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; @@ -26,7 +27,6 @@ import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; // Page specific imports import { Meta } from 'vitreum/headtags'; - const BREWKEY = 'HB_newPage_content'; const STYLEKEY = 'HB_newPage_style'; const METAKEY = 'HB_newPage_metadata'; @@ -51,8 +51,11 @@ const NewPage = (props) => { const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1); const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); const [themeBundle , setThemeBundle ] = useState({}); + const [unsavedChanges , setUnsavedChanges ] = useState(false); + const [autoSaveEnabled , setAutoSaveEnabled ] = useState(false); - const editorRef = useRef(null); + const editorRef = useRef(null); + const lastSavedBrew = useRef(_.cloneDeep(props.brew)); useEffect(() => { loadBrew(); @@ -103,6 +106,13 @@ const NewPage = (props) => { window.history.replaceState({}, window.location.title, '/new/'); }; + useEffect(()=>{ + const hasChange = !_.isEqual(currentBrew, lastSavedBrew.current); + setUnsavedChanges(hasChange); + + if(autoSaveEnabled) trySave(false, hasChange); + }, [currentBrew]); + const handleSplitMove = ()=>{ editorRef.current.update(); }; From 7393aef806e8cda3c2b0e3d84ce5924db8d3d6aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 5 Oct 2025 19:42:01 +0200 Subject: [PATCH 17/20] set up development config variavle --- client/homebrew/homebrew.jsx | 1 + config/default.json | 1 + 2 files changed, 2 insertions(+) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index cfc691407..f670df8ab 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -48,6 +48,7 @@ const Homebrew = (props)=>{ global.config = config; const backgroundObject = ()=>{ + if(!config.development) return null; if(config.deployment || config.local){ const bgText = config.deployment || 'Local'; return { diff --git a/config/default.json b/config/default.json index bea3b2663..0a2d7281e 100644 --- a/config/default.json +++ b/config/default.json @@ -1,4 +1,5 @@ { + "development": true, "host" : "homebrewery.local.naturalcrit.com:8000", "naturalcrit_url" : "local.naturalcrit.com:8010", "secret" : "secret", From c90a8c53a50218c0b605419ba6fba5ddbabb4c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 5 Oct 2025 19:56:50 +0200 Subject: [PATCH 18/20] lets test this --- client/homebrew/homebrew.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index bf51babc8..d62bc6699 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -51,8 +51,8 @@ const Homebrew = (props)=>{ const backgroundObject = ()=>{ if(!config.development) return null; - if(config.deployment || config.local){ - const bgText = config.deployment || 'Local'; + if(global.config.deployment || config.local){ + const bgText = global.config.deployment || 'Local'; return { backgroundImage : `url("data:image/svg+xml;utf8,${bgText}")` }; From 1f51abaf10998210e1ea3a251f3cf2e49dcdfe6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 5 Oct 2025 19:57:49 +0200 Subject: [PATCH 19/20] this makes more sense --- client/homebrew/homebrew.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index d62bc6699..e7e006808 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -50,8 +50,7 @@ const Homebrew = (props)=>{ global.config = config; const backgroundObject = ()=>{ - if(!config.development) return null; - if(global.config.deployment || config.local){ + if(global.config.deployment || (config.local && config.development)){ const bgText = global.config.deployment || 'Local'; return { backgroundImage : `url("data:image/svg+xml;utf8,${bgText}")` From 41aebf084bcee6053993b490604e10da5c3b5541 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sun, 5 Oct 2025 21:57:19 -0400 Subject: [PATCH 20/20] Make the renderSaveButton() function common between edit/new/home Each of the edit/home/new pages renders its save button differently. This makes it a common function with all the same possible render states (does the document have unsaved changes? Is it already saved? Was it auto-saved?). - Common save button - Adds the "save" button to /home page which wasn't there before - Animates the "save" button in /home and /new when the user makes their first change to signal that yes, you do have to actually click the save button if you want to keep this. - "reminder... you haven't saved for X minutes" still not functional on /new and /home since that involves more moving pieces. --- client/homebrew/pages/editPage/editPage.jsx | 12 ++++-- client/homebrew/pages/homePage/homePage.jsx | 43 +++++++++++++++++-- client/homebrew/pages/homePage/homePage.less | 6 +++ client/homebrew/pages/newPage/newPage.jsx | 44 +++++++++++++++----- client/homebrew/pages/newPage/newPage.less | 6 +++ 5 files changed, 93 insertions(+), 18 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 3bd74b786..d4e0061b1 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -46,8 +46,8 @@ const STYLEKEY = 'HB_newPage_style'; const SNIPKEY = 'HB_newPage_snippets'; const METAKEY = 'HB_newPage_meta'; - const useLocalStorage = false; +const neverSaved = false; const EditPage = (props)=>{ props = { @@ -309,14 +309,18 @@ const EditPage = (props)=>{ // #3 - Unsaved changes exist, click to save, show SAVE NOW if(unsavedChanges) - return trySave(true)} color='blue' icon='fas fa-save'>Save Now; + return trySave(true)} color='blue' icon='fas fa-save'>save now; // #4 - No unsaved changes, autosave is ON, show AUTO-SAVED if(autoSaveEnabled) - return auto-saved.; + return auto-saved; + + // #5 - No unsaved changes, and has never been saved, hide the button + if(neverSaved) + return save now; // DEFAULT - No unsaved changes, show SAVED - return saved.; + return saved; }; const toggleAutoSave = ()=>{ diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index cfa6eb59d..fe57a9913 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -33,6 +33,7 @@ const SNIPKEY = 'homebrewery-new-snippets'; const METAKEY = 'homebrewery-new-meta'; const useLocalStorage = false; +const neverSaved = true; const HomePage =(props)=>{ props = { @@ -122,6 +123,41 @@ const HomePage =(props)=>{ } }; + const renderSaveButton = ()=>{ + // #1 - Currently saving, show SAVING + if(isSaving) + return saving...; + + // #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.' + // : `Autosave is OFF, and you haven't saved for ${elapsedTime} minutes.`; + + // return + // Reminder... + //
{text}
+ //
; + // } + + // #3 - Unsaved changes exist, click to save, show SAVE NOW + if(unsavedChanges) + return save now; + + // #4 - No unsaved changes, autosave is ON, show AUTO-SAVED + if(autoSaveEnabled) + return auto-saved; + + // #5 - No unsaved changes, and has never been saved, hide the button + if(neverSaved) + return save now; + + // DEFAULT - No unsaved changes, show SAVED + return saved; + }; + const clearError = ()=>{ setError(null); setIsSaving(false); @@ -130,10 +166,9 @@ const HomePage =(props)=>{ const renderNavbar = ()=>{ return - {error ? - : - null - } + {error + ? + : renderSaveButton()} diff --git a/client/homebrew/pages/homePage/homePage.less b/client/homebrew/pages/homePage/homePage.less index 4cf9ff4fe..c3ec1815c 100644 --- a/client/homebrew/pages/homePage/homePage.less +++ b/client/homebrew/pages/homePage/homePage.less @@ -34,7 +34,13 @@ } .navItem.save { + .fadeInRight(); + .transition(opacity); background-color : @orange; &:hover { background-color : @green; } + &.neverSaved { + .fadeOutRight(); + opacity: 0; + } } } diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index b9b628a2c..bc2b39c44 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -33,8 +33,8 @@ const METAKEY = 'HB_newPage_metadata'; const SNIPKEY = 'HB_newPage_snippets'; const SAVEKEYPREFIX = 'HB_editor_defaultSave_'; - const useLocalStorage = true; +const neverSaved = true; const NewPage = (props) => { props = { @@ -96,6 +96,7 @@ const NewPage = (props) => { const saveStorage = localStorage.getItem(SAVEKEY) || 'HOMEBREWERY'; setCurrentBrew(brew); + lastSavedBrew.current = brew; setSaveGoogle(saveStorage == 'GOOGLE-DRIVE' && saveGoogle); localStorage.setItem(BREWKEY, brew.text); @@ -169,15 +170,38 @@ const NewPage = (props) => { }; const renderSaveButton = ()=>{ - if(isSaving){ - return - save... - ; - } else { - return - save - ; - } + // #1 - Currently saving, show SAVING + if(isSaving) + return saving...; + + // #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.' + // : `Autosave is OFF, and you haven't saved for ${elapsedTime} minutes.`; + + // return + // Reminder... + //
{text}
+ //
; + // } + + // #3 - Unsaved changes exist, click to save, show SAVE NOW + if(unsavedChanges) + return save now; + + // #4 - No unsaved changes, autosave is ON, show AUTO-SAVED + if(autoSaveEnabled) + return auto-saved; + + // #5 - No unsaved changes, and has never been saved, hide the button + if(neverSaved) + return save now; + + // DEFAULT - No unsaved changes, show SAVED + return saved; }; const clearError = ()=>{ diff --git a/client/homebrew/pages/newPage/newPage.less b/client/homebrew/pages/newPage/newPage.less index ebc44d543..083e1ee09 100644 --- a/client/homebrew/pages/newPage/newPage.less +++ b/client/homebrew/pages/newPage/newPage.less @@ -1,6 +1,12 @@ .newPage { .navItem.save { + .fadeInRight(); + .transition(opacity); background-color : @orange; &:hover { background-color : @green; } + &.neverSaved { + .fadeOutRight(); + opacity: 0; + } } }