|
91 | 91 | </div> |
92 | 92 | </template> |
93 | 93 |
|
94 | | -<script lang="ts"> |
95 | | -import { computed, defineComponent, nextTick, PropType, ref, unref, watch } from 'vue' |
| 94 | +<script setup lang="ts"> |
| 95 | +import { computed, nextTick, ref, unref, watch } from 'vue' |
96 | 96 | import { Resource } from '@opencloud-eu/web-client' |
97 | 97 | import { |
98 | 98 | AppConfigObject, |
@@ -120,161 +120,133 @@ const MAX_FONT_SIZE_PERCENTAGE = 150 |
120 | 120 | const MIN_FONT_SIZE_PERCENTAGE = 50 |
121 | 121 | const FONT_SIZE_PERCENTAGE_STEP = 10 |
122 | 122 |
|
123 | | -export default defineComponent({ |
124 | | - name: 'EpubReader', |
125 | | - props: { |
126 | | - applicationConfig: { type: Object as PropType<AppConfigObject>, required: true }, |
127 | | - currentContent: { |
128 | | - type: String, |
129 | | - required: true |
130 | | - }, |
131 | | - isReadOnly: { type: Boolean, required: false }, |
132 | | - resource: { type: Object as PropType<Resource>, required: true } |
133 | | - }, |
134 | | - emits: ['close'], |
135 | | - setup(props) { |
136 | | - const keyboardActions = useKeyboardActions() |
137 | | - const bookContainer = ref<Element>() |
138 | | - const chapters = ref<NavItem[]>([]) |
139 | | - const currentChapter = ref<NavItem>() |
140 | | - const navigateLeftDisabled = ref(false) |
141 | | - const navigateRightDisabled = ref(false) |
142 | | - const localStorageData = useLocalStorage<{ fontSizePercentage?: number }>(`oc_epubReader`, {}) |
143 | | - const currentFontSizePercentage = ref(unref(localStorageData).fontSizePercentage || 100) |
144 | | - const themeStore = useThemeStore() |
145 | | - const book = ref<Book>() |
146 | | - const rendition = ref<Rendition>() |
147 | | -
|
148 | | - const navigateLeft = () => { |
149 | | - unref(rendition).prev() |
150 | | - } |
151 | | -
|
152 | | - const navigateRight = () => { |
153 | | - unref(rendition).next() |
154 | | - } |
155 | | -
|
156 | | - const showChapter = (chapter: NavItem) => { |
157 | | - unref(rendition).display(chapter.href) |
158 | | - } |
| 123 | +const { currentContent, resource } = defineProps<{ |
| 124 | + applicationConfig: AppConfigObject |
| 125 | + currentContent: string |
| 126 | + resource: Resource |
| 127 | + isReadOnly?: boolean |
| 128 | +}>() |
| 129 | +
|
| 130 | +const keyboardActions = useKeyboardActions() |
| 131 | +const bookContainer = ref<Element>() |
| 132 | +const chapters = ref<NavItem[]>([]) |
| 133 | +const currentChapter = ref<NavItem>() |
| 134 | +const navigateLeftDisabled = ref(false) |
| 135 | +const navigateRightDisabled = ref(false) |
| 136 | +const localStorageData = useLocalStorage<{ fontSizePercentage?: number }>(`oc_epubReader`, {}) |
| 137 | +const currentFontSizePercentage = ref(unref(localStorageData).fontSizePercentage || 100) |
| 138 | +const themeStore = useThemeStore() |
| 139 | +const book = ref<Book>() |
| 140 | +const rendition = ref<Rendition>() |
| 141 | +
|
| 142 | +const navigateLeft = () => { |
| 143 | + unref(rendition).prev() |
| 144 | +} |
159 | 145 |
|
160 | | - const increaseFontSize = () => { |
161 | | - currentFontSizePercentage.value = Math.min( |
162 | | - unref(currentFontSizePercentage) + FONT_SIZE_PERCENTAGE_STEP, |
163 | | - MAX_FONT_SIZE_PERCENTAGE |
164 | | - ) |
165 | | - } |
| 146 | +const navigateRight = () => { |
| 147 | + unref(rendition).next() |
| 148 | +} |
166 | 149 |
|
167 | | - const resetFontSize = () => { |
168 | | - currentFontSizePercentage.value = 100 |
169 | | - } |
| 150 | +const showChapter = (chapter: NavItem) => { |
| 151 | + unref(rendition).display(chapter.href) |
| 152 | +} |
170 | 153 |
|
171 | | - const decreaseFontSize = () => { |
172 | | - currentFontSizePercentage.value = Math.max( |
173 | | - unref(currentFontSizePercentage) - FONT_SIZE_PERCENTAGE_STEP, |
174 | | - MIN_FONT_SIZE_PERCENTAGE |
175 | | - ) |
176 | | - } |
| 154 | +const increaseFontSize = () => { |
| 155 | + currentFontSizePercentage.value = Math.min( |
| 156 | + unref(currentFontSizePercentage) + FONT_SIZE_PERCENTAGE_STEP, |
| 157 | + MAX_FONT_SIZE_PERCENTAGE |
| 158 | + ) |
| 159 | +} |
177 | 160 |
|
178 | | - const increaseFontSizeDisabled = computed(() => { |
179 | | - return unref(currentFontSizePercentage) >= MAX_FONT_SIZE_PERCENTAGE |
180 | | - }) |
| 161 | +const resetFontSize = () => { |
| 162 | + currentFontSizePercentage.value = 100 |
| 163 | +} |
181 | 164 |
|
182 | | - const decreaseFontSizeDisabled = computed(() => { |
183 | | - return unref(currentFontSizePercentage) <= MIN_FONT_SIZE_PERCENTAGE |
184 | | - }) |
| 165 | +const decreaseFontSize = () => { |
| 166 | + currentFontSizePercentage.value = Math.max( |
| 167 | + unref(currentFontSizePercentage) - FONT_SIZE_PERCENTAGE_STEP, |
| 168 | + MIN_FONT_SIZE_PERCENTAGE |
| 169 | + ) |
| 170 | +} |
185 | 171 |
|
186 | | - keyboardActions.bindKeyAction({ primary: Key.ArrowLeft }, () => navigateLeft()) |
187 | | - keyboardActions.bindKeyAction({ primary: Key.ArrowRight }, () => navigateRight()) |
| 172 | +const increaseFontSizeDisabled = computed(() => { |
| 173 | + return unref(currentFontSizePercentage) >= MAX_FONT_SIZE_PERCENTAGE |
| 174 | +}) |
188 | 175 |
|
189 | | - watch( |
190 | | - () => props.currentContent, |
191 | | - async () => { |
192 | | - await nextTick() |
| 176 | +const decreaseFontSizeDisabled = computed(() => { |
| 177 | + return unref(currentFontSizePercentage) <= MIN_FONT_SIZE_PERCENTAGE |
| 178 | +}) |
193 | 179 |
|
194 | | - if (unref(book)) { |
195 | | - unref(book).destroy() |
196 | | - } |
| 180 | +keyboardActions.bindKeyAction({ primary: Key.ArrowLeft }, () => navigateLeft()) |
| 181 | +keyboardActions.bindKeyAction({ primary: Key.ArrowRight }, () => navigateRight()) |
197 | 182 |
|
198 | | - const localStorageResourceData = useLocalStorage<{ currentLocation?: Location }>( |
199 | | - `oc_epubReader_resource_${props.resource.id}`, |
200 | | - {} |
201 | | - ) |
| 183 | +watch( |
| 184 | + () => currentContent, |
| 185 | + async () => { |
| 186 | + await nextTick() |
202 | 187 |
|
203 | | - book.value = ePub(props.currentContent) |
| 188 | + if (unref(book)) { |
| 189 | + unref(book).destroy() |
| 190 | + } |
204 | 191 |
|
205 | | - unref(book).loaded.navigation.then(({ toc }) => { |
206 | | - chapters.value = toc |
207 | | - currentChapter.value = toc?.[0] |
208 | | - }) |
| 192 | + const localStorageResourceData = useLocalStorage<{ currentLocation?: Location }>( |
| 193 | + `oc_epubReader_resource_${resource.id}`, |
| 194 | + {} |
| 195 | + ) |
209 | 196 |
|
210 | | - rendition.value = unref(book).renderTo(unref(bookContainer), { |
211 | | - flow: 'paginated', |
212 | | - width: 650, |
213 | | - height: '90%' // Don't use full height to avoid cut-off text |
214 | | - }) |
| 197 | + book.value = ePub(currentContent) |
215 | 198 |
|
216 | | - unref(rendition).themes.register('dark', DARK_THEME_CONFIG) |
217 | | - unref(rendition).themes.register('light', LIGHT_THEME_CONFIG) |
218 | | - unref(rendition).themes.select(themeStore.currentTheme.isDark ? 'dark' : 'light') |
219 | | - unref(rendition).themes.fontSize(`${unref(currentFontSizePercentage)}%`) |
220 | | - unref(rendition).display(unref(localStorageResourceData)?.currentLocation?.start?.cfi) |
| 199 | + unref(book).loaded.navigation.then(({ toc }) => { |
| 200 | + chapters.value = toc |
| 201 | + currentChapter.value = toc?.[0] |
| 202 | + }) |
221 | 203 |
|
222 | | - unref(rendition).on('keydown', (event: KeyboardEvent) => { |
223 | | - if (event.key === Key.ArrowLeft) { |
224 | | - navigateLeft() |
225 | | - } |
226 | | - if (event.key === Key.ArrowRight) { |
227 | | - navigateRight() |
228 | | - } |
229 | | - }) |
| 204 | + rendition.value = unref(book).renderTo(unref(bookContainer), { |
| 205 | + flow: 'paginated', |
| 206 | + width: 650, |
| 207 | + height: '90%' // Don't use full height to avoid cut-off text |
| 208 | + }) |
230 | 209 |
|
231 | | - unref(rendition).on('relocated', () => { |
232 | | - const currentLocation = unref(rendition).currentLocation() as any & Location |
233 | | - localStorageResourceData.value = { currentLocation } |
234 | | - navigateLeftDisabled.value = currentLocation.atStart === true |
235 | | - navigateRightDisabled.value = currentLocation.atEnd === true |
| 210 | + unref(rendition).themes.register('dark', DARK_THEME_CONFIG) |
| 211 | + unref(rendition).themes.register('light', LIGHT_THEME_CONFIG) |
| 212 | + unref(rendition).themes.select(themeStore.currentTheme.isDark ? 'dark' : 'light') |
| 213 | + unref(rendition).themes.fontSize(`${unref(currentFontSizePercentage)}%`) |
| 214 | + unref(rendition).display(unref(localStorageResourceData)?.currentLocation?.start?.cfi) |
236 | 215 |
|
237 | | - const locationCfi = currentLocation.start.cfi |
238 | | - const spineItem = unref(book).spine.get(locationCfi) |
239 | | - const navItem = unref(book).navigation.get(spineItem.href) |
240 | | - // Might be sub nav item and therefore undefined |
241 | | - if (navItem) { |
242 | | - currentChapter.value = navItem |
243 | | - } |
244 | | - }) |
245 | | - }, |
246 | | - { |
247 | | - immediate: true |
| 216 | + unref(rendition).on('keydown', (event: KeyboardEvent) => { |
| 217 | + if (event.key === Key.ArrowLeft) { |
| 218 | + navigateLeft() |
248 | 219 | } |
249 | | - ) |
| 220 | + if (event.key === Key.ArrowRight) { |
| 221 | + navigateRight() |
| 222 | + } |
| 223 | + }) |
250 | 224 |
|
251 | | - watch(currentFontSizePercentage, () => { |
252 | | - unref(rendition).themes.fontSize(`${unref(currentFontSizePercentage)}%`) |
253 | | - localStorageData.value = { |
254 | | - ...unref(localStorageData), |
255 | | - fontSizePercentage: unref(currentFontSizePercentage) |
| 225 | + unref(rendition).on('relocated', () => { |
| 226 | + const currentLocation = unref(rendition).currentLocation() as any & Location |
| 227 | + localStorageResourceData.value = { currentLocation } |
| 228 | + navigateLeftDisabled.value = currentLocation.atStart === true |
| 229 | + navigateRightDisabled.value = currentLocation.atEnd === true |
| 230 | +
|
| 231 | + const locationCfi = currentLocation.start.cfi |
| 232 | + const spineItem = unref(book).spine.get(locationCfi) |
| 233 | + const navItem = unref(book).navigation.get(spineItem.href) |
| 234 | + // Might be sub nav item and therefore undefined |
| 235 | + if (navItem) { |
| 236 | + currentChapter.value = navItem |
256 | 237 | } |
257 | 238 | }) |
| 239 | + }, |
| 240 | + { |
| 241 | + immediate: true |
| 242 | + } |
| 243 | +) |
258 | 244 |
|
259 | | - return { |
260 | | - bookContainer, |
261 | | - navigateLeft, |
262 | | - navigateLeftDisabled, |
263 | | - navigateRight, |
264 | | - navigateRightDisabled, |
265 | | - currentChapter, |
266 | | - chapters, |
267 | | - showChapter, |
268 | | - resetFontSize, |
269 | | - increaseFontSize, |
270 | | - decreaseFontSize, |
271 | | - increaseFontSizeDisabled, |
272 | | - decreaseFontSizeDisabled, |
273 | | - currentFontSizePercentage, |
274 | | - FONT_SIZE_PERCENTAGE_STEP, |
275 | | - rendition, |
276 | | - book |
277 | | - } |
| 245 | +watch(currentFontSizePercentage, () => { |
| 246 | + unref(rendition).themes.fontSize(`${unref(currentFontSizePercentage)}%`) |
| 247 | + localStorageData.value = { |
| 248 | + ...unref(localStorageData), |
| 249 | + fontSizePercentage: unref(currentFontSizePercentage) |
278 | 250 | } |
279 | 251 | }) |
280 | 252 | </script> |
0 commit comments