Skip to content

Commit

Permalink
Merge branch 'master' into addCSSRoute-naturalcrit#1097
Browse files Browse the repository at this point in the history
  • Loading branch information
5e-Cleric authored Aug 25, 2024
2 parents ca5a7a1 + 1803c89 commit 762de62
Show file tree
Hide file tree
Showing 7 changed files with 265 additions and 77 deletions.
52 changes: 28 additions & 24 deletions client/homebrew/brewRenderer/brewRenderer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const _ = require('lodash');
const MarkdownLegacy = require('naturalcrit/markdownLegacy.js');
const Markdown = require('naturalcrit/markdown.js');
const ErrorBar = require('./errorBar/errorBar.jsx');
const ToolBar = require('./toolBar/toolBar.jsx');

//TODO: move to the brew renderer
const RenderWarnings = require('homebrewery/renderWarnings/renderWarnings.jsx');
Expand Down Expand Up @@ -60,10 +61,11 @@ const BrewRenderer = (props)=>{
};

const [state, setState] = useState({
viewablePageNumber : 0,
height : PAGE_HEIGHT,
isMounted : false,
visibility : 'hidden',
height : PAGE_HEIGHT,
isMounted : false,
visibility : 'hidden',
zoom : 100,
currentPageNumber : 1,
});

const mainRef = useRef(null);
Expand All @@ -85,11 +87,14 @@ const BrewRenderer = (props)=>{
}));
};

const handleScroll = (e)=>{
const target = e.target;
const getCurrentPage = (e)=>{
const { scrollTop, clientHeight, scrollHeight } = e.target;
const totalScrollableHeight = scrollHeight - clientHeight;
const currentPageNumber = Math.ceil((scrollTop / totalScrollableHeight) * rawPages.length);

setState((prevState)=>({
...prevState,
viewablePageNumber : Math.floor(target.scrollTop / target.scrollHeight * rawPages.length)
currentPageNumber : currentPageNumber || 1
}));
};

Expand All @@ -100,23 +105,12 @@ const BrewRenderer = (props)=>{
if(index == props.currentEditorPage) //Already rendered before this step
return false;

if(Math.abs(index - state.viewablePageNumber) <= 3)
if(Math.abs(index - state.currentPageNumber) <= 3)
return true;

return false;
};

const renderPageInfo = ()=>{
return <div className='pageInfo' ref={mainRef}>
<div>
{props.renderer}
</div>
<div>
{state.viewablePageNumber + 1} / {rawPages.length}
</div>
</div>;
};

const renderDummyPage = (index)=>{
return <div className='phb page' id={`p${index + 1}`} key={index}>
<i className='fas fa-spinner fa-spin' />
Expand Down Expand Up @@ -186,47 +180,57 @@ const BrewRenderer = (props)=>{
document.dispatchEvent(new MouseEvent('click'));
};

//Toolbar settings:
const handleZoom = (newZoom)=>{
setState((prevState)=>({
...prevState,
zoom : newZoom
}));
};

return (
<>
{/*render dummy page while iFrame is mounting.*/}
{!state.isMounted
? <div className='brewRenderer' onScroll={handleScroll}>
? <div className='brewRenderer' onScroll={getCurrentPage}>
<div className='pages'>
{renderDummyPage(1)}
</div>
</div>
: null}

<ErrorBar errors={props.errors} />
<div className='popups'>
<div className='popups' ref={mainRef}>
<RenderWarnings />
<NotificationPopup />
</div>

<ToolBar onZoomChange={handleZoom} currentPage={state.currentPageNumber} totalPages={rawPages.length}/>

{/*render in iFrame so broken code doesn't crash the site.*/}
<Frame id='BrewRenderer' initialContent={INITIAL_CONTENT}
style={{ width: '100%', height: '100%', visibility: state.visibility }}
contentDidMount={frameDidMount}
onClick={()=>{emitClick();}}
>
<div className={'brewRenderer'}
onScroll={handleScroll}
onScroll={getCurrentPage}
onKeyDown={handleControlKeys}
tabIndex={-1}
style={{ height: state.height }}>

{/* Apply CSS from Style tab and render pages from Markdown tab */}
{state.isMounted
&&
<>
{renderStyle()}
<div className='pages' lang={`${props.lang || 'en'}`}>
<div className='pages' lang={`${props.lang || 'en'}`} style={{ zoom: `${state.zoom}%` }}>
{renderPages()}
</div>
</>
}
</div>
</Frame>
{renderPageInfo()}
</>
);
};
Expand Down
68 changes: 17 additions & 51 deletions client/homebrew/brewRenderer/brewRenderer.less
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
@import (multiple, less) 'shared/naturalcrit/styles/reset.less';

.brewRenderer {
will-change : transform;
overflow-y : scroll;
padding-top : 30px;
overflow-y : scroll;
will-change : transform;
:where(.pages) {
margin : 30px 0px;
& > :where(.page) {
Expand All @@ -14,66 +15,31 @@
box-shadow : 1px 4px 14px #000000;
}
}

&::-webkit-scrollbar {
width: 20px;
&:horizontal{
height: 20px;
width:auto;
width : 20px;
&:horizontal {
width : auto;
height : 20px;
}
&-thumb {
background: linear-gradient(90deg, #d3c1af 15px, #00000000 15px);
&:horizontal{
background: linear-gradient(0deg, #d3c1af 15px, #00000000 15px);
}
}
&-corner {
visibility: hidden;
background : linear-gradient(90deg, #D3C1AF 15px, #00000000 15px);
&:horizontal { background : linear-gradient(0deg, #D3C1AF 15px, #00000000 15px); }
}
&-corner { visibility : hidden; }
}





}

.pane { position : relative; }
.pageInfo {
position : absolute;
right : 17px;
bottom : 0;
z-index : 1000;
font-size : 10px;
font-weight : 800;
color : white;
background-color : #333333;
div {
display : inline-block;
padding : 8px 10px;
&:not(:last-child) { border-right : 1px solid #666666; }
}
}
.ppr_msg {
position : absolute;
bottom : 0;
left : 0px;
z-index : 1000;
padding : 8px 10px;
font-size : 10px;
font-weight : 800;
color : white;
background-color : #333333;
}

@media print {
.toolBar { display : none; }
.brewRenderer {
height: 100%;
overflow-y: unset;
height : 100%;
padding-top : unset;
overflow-y : unset;
.pages {
margin: 0px;
&>.page {
box-shadow: unset;
}
margin : 0px;
& > .page { box-shadow : unset; }
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
.popups {
position : fixed;
top : @navbarHeight;
top : calc(@navbarHeight + @viewerToolsHeight);
right : 24px;
z-index : 10001;
width : 450px;
margin-top : 5px;
}

.notificationPopup {
Expand Down
119 changes: 119 additions & 0 deletions client/homebrew/brewRenderer/toolBar/toolBar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
require('./toolBar.less');
const React = require('react');
const { useState, useEffect } = React;
const _ = require('lodash');

const MAX_ZOOM = 300;
const MIN_ZOOM = 10;

const ToolBar = ({ onZoomChange, currentPage, onPageChange, totalPages })=>{

const [zoomLevel, setZoomLevel] = useState(100);
const [pageNum, setPageNum] = useState(currentPage);

useEffect(()=>{
onZoomChange(zoomLevel);
}, [zoomLevel]);

useEffect(()=>{
setPageNum(currentPage);
}, [currentPage]);

const handleZoomButton = (delta)=>{
setZoomLevel(_.clamp(zoomLevel + delta, MIN_ZOOM, MAX_ZOOM));
};

const handlePageInput = (pageInput)=>{
if(/[0-9]/.test(pageInput))
setPageNum(parseInt(pageInput)); // input type is 'text', so `page` comes in as a string, not number.
};

const scrollToPage = (pageNumber)=>{
pageNumber = _.clamp(pageNumber, 1, totalPages);
const iframe = document.getElementById('BrewRenderer');
const brewRenderer = iframe?.contentWindow?.document.querySelector('.brewRenderer');
const page = brewRenderer?.querySelector(`#p${pageNumber}`);
page?.scrollIntoView({ block: 'start' });
setPageNum(pageNumber);
};

return (
<div className='toolBar'>
{/*v=====----------------------< Zoom Controls >---------------------=====v*/}
<div className='group'>
<button
id='zoom-out'
className='tool'
onClick={()=>handleZoomButton(-20)}
disabled={zoomLevel <= MIN_ZOOM}
>
<i className='fas fa-magnifying-glass-minus' />
</button>
<input
id='zoom-slider'
className='range-input tool'
type='range'
name='zoom'
list='zoomLevels'
min={MIN_ZOOM}
max={MAX_ZOOM}
step='1'
value={zoomLevel}
onChange={(e)=>setZoomLevel(parseInt(e.target.value))}
/>
<datalist id='zoomLevels'>
<option value='100' />
</datalist>

<button
id='zoom-in'
className='tool'
onClick={()=>handleZoomButton(20)}
disabled={zoomLevel >= MAX_ZOOM}
>
<i className='fas fa-magnifying-glass-plus' />
</button>
</div>

{/*v=====----------------------< Page Controls >---------------------=====v*/}
<div className='group'>
<button
id='previous-page'
className='previousPage tool'
onClick={()=>scrollToPage(pageNum - 1)}
disabled={pageNum <= 1}
>
<i className='fas fa-arrow-left'></i>
</button>

<div className='tool'>
<input
id='page-input'
className='text-input'
type='text'
name='page'
inputMode='numeric'
pattern='[0-9]'
value={pageNum}
onClick={(e)=>e.target.select()}
onChange={(e)=>handlePageInput(e.target.value)}
onBlur={()=>scrollToPage(pageNum)}
onKeyDown={(e)=>e.key == 'Enter' && scrollToPage(pageNum)}
/>
<span id='page-count'>/ {totalPages}</span>
</div>

<button
id='next-page'
className='tool'
onClick={()=>scrollToPage(pageNum + 1)}
disabled={pageNum >= totalPages}
>
<i className='fas fa-arrow-right'></i>
</button>
</div>
</div>
);
};

module.exports = ToolBar;
Loading

0 comments on commit 762de62

Please sign in to comment.