11'use client' ;
22
3- import { Fragment , useState , useRef , useCallback , useEffect } from 'react' ;
3+ import { Fragment , useState , useRef , useEffect } from 'react' ;
44import { Dialog , DialogPanel , Transition , TransitionChild , Listbox , ListboxButton , ListboxOptions , ListboxOption , Button } from '@headlessui/react' ;
55import { useConfig , ViewType } from '@/contexts/ConfigContext' ;
66import { ChevronUpDownIcon , CheckIcon } from '@/components/icons/Icons' ;
@@ -21,32 +21,54 @@ const viewTypes = [
2121] ;
2222
2323export function DocumentSettings ( { isOpen, setIsOpen, epub } : DocViewSettingsProps ) {
24- const { viewType, skipBlank, epubTheme, textExtractionMargin, updateConfigKey } = useConfig ( ) ;
24+ const {
25+ viewType,
26+ skipBlank,
27+ epubTheme,
28+ headerMargin,
29+ footerMargin,
30+ leftMargin,
31+ rightMargin,
32+ updateConfigKey
33+ } = useConfig ( ) ;
2534 const { createFullAudioBook } = useEPUB ( ) ;
2635 const [ progress , setProgress ] = useState ( 0 ) ;
2736 const [ isGenerating , setIsGenerating ] = useState ( false ) ;
28- const [ localMargin , setLocalMargin ] = useState ( textExtractionMargin ) ;
37+ const [ localMargins , setLocalMargins ] = useState ( {
38+ header : headerMargin ,
39+ footer : footerMargin ,
40+ left : leftMargin ,
41+ right : rightMargin
42+ } ) ;
2943 const abortControllerRef = useRef < AbortController | null > ( null ) ;
3044 const selectedView = viewTypes . find ( v => v . id === viewType ) || viewTypes [ 0 ] ;
3145
32- //console.log(localMargin, textExtractionMargin);
33-
34- // Sync local margin with global state
46+ // Sync local margins with global state
3547 useEffect ( ( ) => {
36- setLocalMargin ( textExtractionMargin ) ;
37- } , [ textExtractionMargin ] ) ;
48+ setLocalMargins ( {
49+ header : headerMargin ,
50+ footer : footerMargin ,
51+ left : leftMargin ,
52+ right : rightMargin
53+ } ) ;
54+ } , [ headerMargin , footerMargin , leftMargin , rightMargin ] ) ;
3855
3956 // Handler for slider change (updates local state only)
40- const handleMarginChange = useCallback ( ( event : React . ChangeEvent < HTMLInputElement > ) => {
41- setLocalMargin ( Number ( event . target . value ) ) ;
42- } , [ ] ) ;
57+ const handleMarginChange = ( margin : keyof typeof localMargins ) => ( event : React . ChangeEvent < HTMLInputElement > ) => {
58+ setLocalMargins ( prev => ( {
59+ ...prev ,
60+ [ margin ] : Number ( event . target . value )
61+ } ) ) ;
62+ } ;
4363
4464 // Handler for slider release
45- const handleMarginChangeComplete = useCallback ( ( ) => {
46- if ( localMargin !== textExtractionMargin ) {
47- updateConfigKey ( 'textExtractionMargin' , localMargin ) ;
65+ const handleMarginChangeComplete = ( margin : keyof typeof localMargins ) => ( ) => {
66+ const value = localMargins [ margin ] ;
67+ const configKey = `${ margin } Margin` ;
68+ if ( value !== ( useConfig ) [ configKey as keyof typeof useConfig ] ) {
69+ updateConfigKey ( configKey as 'headerMargin' | 'footerMargin' | 'leftMargin' | 'rightMargin' , value ) ;
4870 }
49- } , [ localMargin , textExtractionMargin , updateConfigKey ] ) ;
71+ } ;
5072
5173 const handleStartGeneration = async ( ) => {
5274 setIsGenerating ( true ) ;
@@ -154,28 +176,92 @@ export function DocumentSettings({ isOpen, setIsOpen, epub }: DocViewSettingsPro
154176 </ div > }
155177 { ! epub && < div className = "space-y-6" >
156178 < div className = "mt-4 space-y-2" >
157- < label className = "block text-sm font-medium text-foreground" >
158- Text Extraction Margin
179+ < label className = "block text-sm font-medium text-foreground mb-4 " >
180+ Adjust extraction margins (experimental)
159181 </ label >
160- < div className = "flex justify-between" >
161- < span className = "text-xs" > 0%</ span >
162- < span className = "text-xs font-bold" > { Math . round ( localMargin * 100 ) } %</ span >
163- < span className = "text-xs" > 20%</ span >
182+ < div className = "grid grid-cols-1 sm:grid-cols-2 gap-2" >
183+ { /* Header Margin */ }
184+ < div className = "space-y-1" >
185+ < div className = "flex justify-between" >
186+ < span className = "text-xs" > Header</ span >
187+ < span className = "text-xs font-bold" > { Math . round ( localMargins . header * 100 ) } %</ span >
188+ </ div >
189+ < input
190+ type = "range"
191+ min = "0"
192+ max = "0.2"
193+ step = "0.01"
194+ value = { localMargins . header }
195+ onChange = { handleMarginChange ( 'header' ) }
196+ onMouseUp = { handleMarginChangeComplete ( 'header' ) }
197+ onKeyUp = { handleMarginChangeComplete ( 'header' ) }
198+ onTouchEnd = { handleMarginChangeComplete ( 'header' ) }
199+ className = "w-full bg-offbase rounded-lg appearance-none cursor-pointer accent-accent [&::-webkit-slider-runnable-track]:bg-offbase [&::-webkit-slider-runnable-track]:rounded-lg [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-accent [&::-moz-range-track]:bg-offbase [&::-moz-range-track]:rounded-lg [&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-accent"
200+ />
201+ </ div >
202+
203+ { /* Footer Margin */ }
204+ < div className = "space-y-1" >
205+ < div className = "flex justify-between" >
206+ < span className = "text-xs" > Footer</ span >
207+ < span className = "text-xs font-bold" > { Math . round ( localMargins . footer * 100 ) } %</ span >
208+ </ div >
209+ < input
210+ type = "range"
211+ min = "0"
212+ max = "0.2"
213+ step = "0.01"
214+ value = { localMargins . footer }
215+ onChange = { handleMarginChange ( 'footer' ) }
216+ onMouseUp = { handleMarginChangeComplete ( 'footer' ) }
217+ onKeyUp = { handleMarginChangeComplete ( 'footer' ) }
218+ onTouchEnd = { handleMarginChangeComplete ( 'footer' ) }
219+ className = "w-full bg-offbase rounded-lg appearance-none cursor-pointer accent-accent [&::-webkit-slider-runnable-track]:bg-offbase [&::-webkit-slider-runnable-track]:rounded-lg [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-accent [&::-moz-range-track]:bg-offbase [&::-moz-range-track]:rounded-lg [&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-accent"
220+ />
221+ </ div >
222+
223+ { /* Left Margin */ }
224+ < div className = "space-y-1" >
225+ < div className = "flex justify-between" >
226+ < span className = "text-xs" > Left</ span >
227+ < span className = "text-xs font-bold" > { Math . round ( localMargins . left * 100 ) } %</ span >
228+ </ div >
229+ < input
230+ type = "range"
231+ min = "0"
232+ max = "0.2"
233+ step = "0.01"
234+ value = { localMargins . left }
235+ onChange = { handleMarginChange ( 'left' ) }
236+ onMouseUp = { handleMarginChangeComplete ( 'left' ) }
237+ onKeyUp = { handleMarginChangeComplete ( 'left' ) }
238+ onTouchEnd = { handleMarginChangeComplete ( 'left' ) }
239+ className = "w-full bg-offbase rounded-lg appearance-none cursor-pointer accent-accent [&::-webkit-slider-runnable-track]:bg-offbase [&::-webkit-slider-runnable-track]:rounded-lg [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-accent [&::-moz-range-track]:bg-offbase [&::-moz-range-track]:rounded-lg [&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-accent"
240+ />
241+ </ div >
242+
243+ { /* Right Margin */ }
244+ < div className = "space-y-1" >
245+ < div className = "flex justify-between" >
246+ < span className = "text-xs" > Right</ span >
247+ < span className = "text-xs font-bold" > { Math . round ( localMargins . right * 100 ) } %</ span >
248+ </ div >
249+ < input
250+ type = "range"
251+ min = "0"
252+ max = "0.2"
253+ step = "0.01"
254+ value = { localMargins . right }
255+ onChange = { handleMarginChange ( 'right' ) }
256+ onMouseUp = { handleMarginChangeComplete ( 'right' ) }
257+ onKeyUp = { handleMarginChangeComplete ( 'right' ) }
258+ onTouchEnd = { handleMarginChangeComplete ( 'right' ) }
259+ className = "w-full bg-offbase rounded-lg appearance-none cursor-pointer accent-accent [&::-webkit-slider-runnable-track]:bg-offbase [&::-webkit-slider-runnable-track]:rounded-lg [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-accent [&::-moz-range-track]:bg-offbase [&::-moz-range-track]:rounded-lg [&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-accent"
260+ />
261+ </ div >
164262 </ div >
165- < input
166- type = "range"
167- min = "0"
168- max = "0.2"
169- step = "0.01"
170- value = { localMargin }
171- onChange = { handleMarginChange }
172- onMouseUp = { handleMarginChangeComplete }
173- onKeyUp = { handleMarginChangeComplete }
174- onTouchEnd = { handleMarginChangeComplete }
175- className = "w-full bg-offbase rounded-lg appearance-none cursor-pointer accent-accent [&::-webkit-slider-runnable-track]:bg-offbase [&::-webkit-slider-runnable-track]:rounded-lg [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-accent [&::-moz-range-track]:bg-offbase [&::-moz-range-track]:rounded-lg [&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-accent"
176- />
177- < p className = "text-xs text-muted" >
178- { "Don't" } include content from outer rim of the page during text extraction (experimental)
263+ < p className = "text-xs text-muted mt-2" >
264+ Adjust margins to exclude content from edges of the page during text extraction
179265 </ p >
180266 </ div >
181267 < Listbox
0 commit comments