|
1 | 1 | 'use client'; |
2 | 2 |
|
3 | 3 | import { Fragment, useState, useRef } from 'react'; |
4 | | -import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild, Listbox, ListboxButton, ListboxOptions, ListboxOption, Button } from '@headlessui/react'; |
| 4 | +import { Dialog, DialogPanel, Transition, TransitionChild, Listbox, ListboxButton, ListboxOptions, ListboxOption, Button } from '@headlessui/react'; |
5 | 5 | import { useConfig, ViewType } from '@/contexts/ConfigContext'; |
6 | 6 | import { ChevronUpDownIcon, CheckIcon } from '@/components/icons/Icons'; |
7 | 7 | import { useEPUB } from '@/contexts/EPUBContext'; |
8 | 8 |
|
| 9 | +const isDev = process.env.NEXT_PUBLIC_NODE_ENV !== 'production' || process.env.NODE_ENV == null; |
| 10 | + |
9 | 11 | interface DocViewSettingsProps { |
10 | 12 | isOpen: boolean; |
11 | 13 | setIsOpen: (isOpen: boolean) => void; |
@@ -93,136 +95,126 @@ export function DocumentSettings({ isOpen, setIsOpen, epub }: DocViewSettingsPro |
93 | 95 | leaveTo="opacity-0 scale-95" |
94 | 96 | > |
95 | 97 | <DialogPanel className="w-full max-w-md transform rounded-2xl bg-base p-6 text-left align-middle shadow-xl transition-all"> |
96 | | - <DialogTitle |
97 | | - as="h3" |
98 | | - className="text-lg font-semibold leading-6 text-foreground" |
99 | | - > |
100 | | - View Settings |
101 | | - </DialogTitle> |
102 | | - <div className="mt-4"> |
103 | | - <div className="space-y-4"> |
104 | | - {!epub && <div className="space-y-2"> |
105 | | - <label className="block text-sm font-medium text-foreground">Mode</label> |
106 | | - <Listbox |
107 | | - value={selectedView} |
108 | | - onChange={(newView) => updateConfigKey('viewType', newView.id as ViewType)} |
| 98 | + <div className="space-y-4"> |
| 99 | + {isDev && <div className="space-y-2 pb-2"> |
| 100 | + {!isGenerating ? ( |
| 101 | + <Button |
| 102 | + type="button" |
| 103 | + className="w-full inline-flex justify-center rounded-lg bg-accent px-4 py-2 text-sm |
| 104 | + font-medium text-background hover:opacity-95 focus:outline-none |
| 105 | + focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 |
| 106 | + transform transition-transform duration-200 ease-in-out hover:scale-[1.04]" |
| 107 | + onClick={handleStartGeneration} |
109 | 108 | > |
110 | | - <div className="relative z-10"> |
111 | | - <ListboxButton className="relative w-full cursor-pointer rounded-lg bg-background py-2 pl-3 pr-10 text-left text-foreground shadow-sm focus:outline-none focus:ring-2 focus:ring-accent transform transition-transform duration-200 ease-in-out hover:scale-[1.01] hover:text-accent"> |
112 | | - <span className="block truncate">{selectedView.name}</span> |
113 | | - <span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"> |
114 | | - <ChevronUpDownIcon className="h-5 w-5 text-muted" /> |
115 | | - </span> |
116 | | - </ListboxButton> |
117 | | - <Transition |
118 | | - as={Fragment} |
119 | | - leave="transition ease-in duration-100" |
120 | | - leaveFrom="opacity-100" |
121 | | - leaveTo="opacity-0" |
| 109 | + Export to Audiobook (experimental) |
| 110 | + </Button> |
| 111 | + ) : ( |
| 112 | + <div className="space-y-2"> |
| 113 | + <div className="w-full bg-background rounded-lg overflow-hidden"> |
| 114 | + <div |
| 115 | + className="h-2 bg-accent transition-all duration-300 ease-in-out" |
| 116 | + style={{ width: `${progress}%` }} |
| 117 | + /> |
| 118 | + </div> |
| 119 | + <div className="flex justify-between items-center text-sm text-muted"> |
| 120 | + <span>{Math.round(progress)}% complete</span> |
| 121 | + <Button |
| 122 | + type="button" |
| 123 | + className="inline-flex justify-center rounded-lg px-2.5 py-1 text-sm |
| 124 | + font-medium text-foreground hover:text-accent focus:outline-none |
| 125 | + focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 |
| 126 | + transform transition-transform duration-200 ease-in-out hover:scale-[1.02]" |
| 127 | + onClick={handleCancel} |
122 | 128 | > |
123 | | - <ListboxOptions className="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-background py-1 shadow-lg ring-1 ring-black/5 focus:outline-none"> |
124 | | - {viewTypes.map((view) => ( |
125 | | - <ListboxOption |
126 | | - key={view.id} |
127 | | - className={({ active }) => |
128 | | - `relative cursor-pointer select-none py-2 pl-10 pr-4 ${active ? 'bg-accent/10 text-accent' : 'text-foreground' |
129 | | - }` |
130 | | - } |
131 | | - value={view} |
132 | | - > |
133 | | - {({ selected }) => ( |
134 | | - <> |
135 | | - <span className={`block truncate ${selected ? 'font-medium' : 'font-normal'}`}> |
136 | | - {view.name} |
137 | | - </span> |
138 | | - {selected ? ( |
139 | | - <span className="absolute inset-y-0 left-0 flex items-center pl-3 text-accent"> |
140 | | - <CheckIcon className="h-5 w-5" /> |
141 | | - </span> |
142 | | - ) : null} |
143 | | - </> |
144 | | - )} |
145 | | - </ListboxOption> |
146 | | - ))} |
147 | | - </ListboxOptions> |
148 | | - </Transition> |
| 129 | + Cancel and download |
| 130 | + </Button> |
149 | 131 | </div> |
150 | | - </Listbox> |
151 | | - {selectedView.id === 'scroll' && ( |
152 | | - <p className="text-sm text-warning pt-2"> |
153 | | - Note: Continuous scroll may perform poorly for larger documents. |
154 | | - </p> |
155 | | - )} |
156 | | - </div>} |
| 132 | + </div> |
| 133 | + )} |
| 134 | + </div>} |
| 135 | + {!epub && <div className="space-y-2"> |
| 136 | + <label className="block text-sm font-medium text-foreground">Mode</label> |
| 137 | + <Listbox |
| 138 | + value={selectedView} |
| 139 | + onChange={(newView) => updateConfigKey('viewType', newView.id as ViewType)} |
| 140 | + > |
| 141 | + <div className="relative z-10"> |
| 142 | + <ListboxButton className="relative w-full cursor-pointer rounded-lg bg-background py-2 pl-3 pr-10 text-left text-foreground shadow-sm focus:outline-none focus:ring-2 focus:ring-accent transform transition-transform duration-200 ease-in-out hover:scale-[1.01] hover:text-accent"> |
| 143 | + <span className="block truncate">{selectedView.name}</span> |
| 144 | + <span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"> |
| 145 | + <ChevronUpDownIcon className="h-5 w-5 text-muted" /> |
| 146 | + </span> |
| 147 | + </ListboxButton> |
| 148 | + <Transition |
| 149 | + as={Fragment} |
| 150 | + leave="transition ease-in duration-100" |
| 151 | + leaveFrom="opacity-100" |
| 152 | + leaveTo="opacity-0" |
| 153 | + > |
| 154 | + <ListboxOptions className="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-background py-1 shadow-lg ring-1 ring-black/5 focus:outline-none"> |
| 155 | + {viewTypes.map((view) => ( |
| 156 | + <ListboxOption |
| 157 | + key={view.id} |
| 158 | + className={({ active }) => |
| 159 | + `relative cursor-pointer select-none py-2 pl-10 pr-4 ${active ? 'bg-accent/10 text-accent' : 'text-foreground' |
| 160 | + }` |
| 161 | + } |
| 162 | + value={view} |
| 163 | + > |
| 164 | + {({ selected }) => ( |
| 165 | + <> |
| 166 | + <span className={`block truncate ${selected ? 'font-medium' : 'font-normal'}`}> |
| 167 | + {view.name} |
| 168 | + </span> |
| 169 | + {selected ? ( |
| 170 | + <span className="absolute inset-y-0 left-0 flex items-center pl-3 text-accent"> |
| 171 | + <CheckIcon className="h-5 w-5" /> |
| 172 | + </span> |
| 173 | + ) : null} |
| 174 | + </> |
| 175 | + )} |
| 176 | + </ListboxOption> |
| 177 | + ))} |
| 178 | + </ListboxOptions> |
| 179 | + </Transition> |
| 180 | + </div> |
| 181 | + </Listbox> |
| 182 | + {selectedView.id === 'scroll' && ( |
| 183 | + <p className="text-sm text-warning pt-2"> |
| 184 | + Note: Continuous scroll may perform poorly for larger documents. |
| 185 | + </p> |
| 186 | + )} |
| 187 | + </div>} |
| 188 | + <div className="space-y-2"> |
| 189 | + <label className="flex items-center space-x-2"> |
| 190 | + <input |
| 191 | + type="checkbox" |
| 192 | + checked={skipBlank} |
| 193 | + onChange={(e) => updateConfigKey('skipBlank', e.target.checked)} |
| 194 | + className="form-checkbox h-4 w-4 text-accent rounded border-muted" |
| 195 | + /> |
| 196 | + <span className="text-sm font-medium text-foreground">Skip blank pages</span> |
| 197 | + </label> |
| 198 | + <p className="text-sm text-muted pl-6"> |
| 199 | + Automatically skip pages with no text content |
| 200 | + </p> |
| 201 | + </div> |
| 202 | + {epub && ( |
157 | 203 | <div className="space-y-2"> |
158 | 204 | <label className="flex items-center space-x-2"> |
159 | 205 | <input |
160 | 206 | type="checkbox" |
161 | | - checked={skipBlank} |
162 | | - onChange={(e) => updateConfigKey('skipBlank', e.target.checked)} |
| 207 | + checked={epubTheme} |
| 208 | + onChange={(e) => updateConfigKey('epubTheme', e.target.checked)} |
163 | 209 | className="form-checkbox h-4 w-4 text-accent rounded border-muted" |
164 | 210 | /> |
165 | | - <span className="text-sm font-medium text-foreground">Skip blank pages</span> |
| 211 | + <span className="text-sm font-medium text-foreground">Use theme (experimental)</span> |
166 | 212 | </label> |
167 | 213 | <p className="text-sm text-muted pl-6"> |
168 | | - Automatically skip pages with no text content |
| 214 | + Apply the current app theme to the EPUB viewer |
169 | 215 | </p> |
170 | 216 | </div> |
171 | | - {epub && ( |
172 | | - <> |
173 | | - <div className="space-y-2"> |
174 | | - <label className="flex items-center space-x-2"> |
175 | | - <input |
176 | | - type="checkbox" |
177 | | - checked={epubTheme} |
178 | | - onChange={(e) => updateConfigKey('epubTheme', e.target.checked)} |
179 | | - className="form-checkbox h-4 w-4 text-accent rounded border-muted" |
180 | | - /> |
181 | | - <span className="text-sm font-medium text-foreground">Use theme (experimental)</span> |
182 | | - </label> |
183 | | - <p className="text-sm text-muted pl-6"> |
184 | | - Apply the current app theme to the EPUB viewer |
185 | | - </p> |
186 | | - </div> |
187 | | - <div className="mt-4 space-y-2"> |
188 | | - {!isGenerating ? ( |
189 | | - <Button |
190 | | - type="button" |
191 | | - className="w-full inline-flex justify-center rounded-lg bg-accent px-4 py-2 text-sm |
192 | | - font-medium text-background hover:opacity-95 focus:outline-none |
193 | | - focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 |
194 | | - transform transition-transform duration-200 ease-in-out hover:scale-[1.04]" |
195 | | - onClick={handleStartGeneration} |
196 | | - > |
197 | | - Export to Audiobook (.mp3) |
198 | | - </Button> |
199 | | - ) : ( |
200 | | - <div className="space-y-2"> |
201 | | - <div className="w-full bg-background rounded-lg overflow-hidden"> |
202 | | - <div |
203 | | - className="h-2 bg-accent transition-all duration-300 ease-in-out" |
204 | | - style={{ width: `${progress}%` }} |
205 | | - /> |
206 | | - </div> |
207 | | - <div className="flex justify-between items-center text-sm text-muted"> |
208 | | - <span>{Math.round(progress)}% complete</span> |
209 | | - <Button |
210 | | - type="button" |
211 | | - className="inline-flex justify-center rounded-lg px-2.5 py-1 text-sm |
212 | | - font-medium text-foreground hover:text-accent focus:outline-none |
213 | | - focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 |
214 | | - transform transition-transform duration-200 ease-in-out hover:scale-[1.02]" |
215 | | - onClick={handleCancel} |
216 | | - > |
217 | | - Cancel and download |
218 | | - </Button> |
219 | | - </div> |
220 | | - </div> |
221 | | - )} |
222 | | - </div> |
223 | | - </> |
224 | | - )} |
225 | | - </div> |
| 217 | + )} |
226 | 218 | </div> |
227 | 219 |
|
228 | 220 | <div className="mt-3 flex justify-end"> |
|
0 commit comments