Skip to content

Commit

Permalink
feat: set proper image mime type and add open image functionality (#370)
Browse files Browse the repository at this point in the history
  • Loading branch information
Renji-XD authored Oct 6, 2024
1 parent a9c2576 commit c776709
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 8 deletions.
5 changes: 4 additions & 1 deletion apps/web/src/lib/components/book-card/book-card.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
objectUrl = '';
}
if (typeof value !== 'string') {
objectUrl = URL.createObjectURL(value);
objectUrl = URL.createObjectURL(
value.type ? value : new Blob([value], { type: 'image/jpeg' })
);
return objectUrl;
}
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/lib/components/book-reader/book-reader.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
const reactiveElements$ = iffBrowser(() => of(document)).pipe(
mergeMap((document) => {
const reactiveElementsFn = reactiveElements(document, furiganaStyle);
const reactiveElementsFn = reactiveElements(document, furiganaStyle, hideSpoilerImage);
return contentEl$.pipe(mergeMap((contentEl) => reactiveElementsFn(contentEl)));
}),
reduceToEmptyString()
Expand Down
36 changes: 33 additions & 3 deletions apps/web/src/lib/components/book-reader/reactive-elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,26 @@
* All rights reserved.
*/

import { NEVER, fromEvent, merge, take, tap } from 'rxjs';
import { NEVER, filter, fromEvent, merge, switchMap, take, takeUntil, tap, timer } from 'rxjs';

import { FuriganaStyle } from '../../data/furigana-style';
import { nextChapter$ } from '$lib/components/book-reader/book-toc/book-toc';
import { toggleImageGalleryPictureSpoiler$ } from '$lib/components/book-reader/book-reader-image-gallery/book-reader-image-gallery';

export function reactiveElements(document: Document, furiganaStyle: FuriganaStyle) {
export function reactiveElements(
document: Document,
furiganaStyle: FuriganaStyle,
hideSpoilerImage: boolean
) {
const anchorTagDocumentListener = anchorTagListener(document);
const spoilerImageDocumentListener = spoilerImageListener(document);

return (contentEl: HTMLElement) =>
merge(
anchorTagDocumentListener(contentEl),
rubyTagListener(contentEl, furiganaStyle),
spoilerImageDocumentListener(contentEl)
spoilerImageDocumentListener(contentEl),
openImageInNewTab(contentEl, hideSpoilerImage)
);
}

Expand Down Expand Up @@ -81,6 +86,8 @@ function spoilerImageListener(document: Document) {
el.removeChild(spoilerLabelEl);
el.removeAttribute('data-ttu-spoiler-img');

imageElement?.classList.add('ttu-unspoilered');

toggleImageGalleryPictureSpoiler(imageElement, true);
})
);
Expand All @@ -89,6 +96,29 @@ function spoilerImageListener(document: Document) {
};
}

function openImageInNewTab(contentEl: HTMLElement, hideSpoilerImage: boolean) {
return merge(
...[...contentEl.querySelectorAll('img,image')].map((elm) =>
fromEvent(elm, 'pointerdown').pipe(
switchMap(() => timer(1000).pipe(takeUntil(fromEvent(elm, 'pointerup')))),
filter(
() =>
!hideSpoilerImage ||
elm.classList.contains('ttu-unspoilered') ||
!elm.closest('span[data-ttu-spoiler-img]')
),
tap(() => {
const src = elm.getAttribute('src') || elm.getAttribute('href');

if (src) {
window.open(src, '_blank');
}
})
)
)
);
}

function toggleImageGalleryPictureSpoiler(imageElement: Element | null, unspoilered: boolean) {
if (imageElement instanceof HTMLImageElement) {
toggleImageGalleryPictureSpoiler$.next({ url: imageElement.src, unspoilered });
Expand Down
20 changes: 18 additions & 2 deletions apps/web/src/lib/data/storage/handler/base-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,22 @@ export abstract class BaseStorageHandler {
return `${BaseStorageHandler.readingGoalsFilePrefix}${exporterVersion}_${currentDbVersion}_${lastGoalModified}.json`;
}

static getImageMimeTypeFromExtension(value: string) {
const extension = value.split('.').pop()?.toLowerCase() || '';

switch (extension) {
case 'svg':
return `image/svg+xml`;
case 'png':
case 'gif':
case 'bmp':
case 'webp':
return `image/${extension}`;
default:
return 'image/jpeg';
}
}

protected static checkIsPresentAndUpToDate<T>(
functionToCall: (_: string) => any,
keyToCheck: keyof T,
Expand Down Expand Up @@ -570,15 +586,15 @@ export abstract class BaseStorageHandler {
const existingBlobEntries = bookObject.blobs || {};

existingBlobEntries[imagePath] = await this.readFromZip(
new BlobWriter(),
new BlobWriter(BaseStorageHandler.getImageMimeTypeFromExtension(imagePath)),
'Unable to read blob data',
entry,
progressPerStep
);
bookObject.blobs = existingBlobEntries;
} else if (entry.filename.startsWith('cover.')) {
bookObject.coverImage = await this.readFromZip(
new BlobWriter(),
new BlobWriter(BaseStorageHandler.getImageMimeTypeFromExtension(entry.filename)),
'Unable to read cover data',
entry,
progressPerStep
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { BlurMode } from '$lib/data/blur-mode';
import type { BooksDbBookData } from '$lib/data/database/books-db/versions/books-db';
import { Observable } from 'rxjs';
import { BaseStorageHandler } from '$lib/data/storage/handler/base-handler';
import buildDummyBookImage from '$lib/functions/file-loaders/utils/build-dummy-book-image';
import { isElementGaiji } from '$lib/functions/is-element-gaiji';
import { map } from 'rxjs/operators';
Expand Down Expand Up @@ -46,7 +47,11 @@ function getHtmlWithImageSource(bookData: BooksDbBookData, isPaginated: boolean)
let { elementHtml } = bookData;

Object.entries(blobs).forEach(([key, value]) => {
const url = URL.createObjectURL(value);
const url = URL.createObjectURL(
value.type
? value
: new Blob([value], { type: BaseStorageHandler.getImageMimeTypeFromExtension(key) })
);
const dummyUrl = buildDummyBookImage(key);

objectUrls.push(url);
Expand Down

0 comments on commit c776709

Please sign in to comment.