Skip to content

Commit

Permalink
batch media lookups, eliminate base64ing
Browse files Browse the repository at this point in the history
  • Loading branch information
djahandarie committed Oct 13, 2024
1 parent ace6663 commit b0837a3
Show file tree
Hide file tree
Showing 17 changed files with 314 additions and 301 deletions.
7 changes: 1 addition & 6 deletions dev/data/structured-content-overrides.css
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,8 @@
line-height: initial;
color: initial;
}
.gloss-image-background {
background-color: currentColor;
}
:root[data-browser=firefox] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image,
:root[data-browser=firefox] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image-background,
:root[data-browser=firefox-mobile] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image,
:root[data-browser=firefox-mobile] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image-background {
:root[data-browser=firefox-mobile] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image {
/* remove-rule */
}
.gloss-image-link-text {
Expand Down
63 changes: 4 additions & 59 deletions ext/css/structured-content.css
Original file line number Diff line number Diff line change
Expand Up @@ -67,62 +67,32 @@
text-align: center;
padding: 0.25em;
}
.gloss-image-background {
--image: none;

position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: var(--text-color);
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center center;
-webkit-mask-mode: alpha;
-webkit-mask-size: contain;
-webkit-mask-image: var(--image);
mask-repeat: no-repeat;
mask-position: center center;
mask-mode: alpha;
mask-size: contain;
mask-image: var(--image);
}
.gloss-image {
display: inline-block;
vertical-align: top;
object-fit: contain;
border: none;
outline: none;
}
.gloss-image-link[data-has-aspect-ratio=true] .gloss-image {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.gloss-image:not([src]) {
display: none;
}
.gloss-image-link[data-image-rendering=pixelated] .gloss-image,
.gloss-image-link[data-image-rendering=pixelated] .gloss-image-background {
.gloss-image-link[data-image-rendering=pixelated] .gloss-image {
image-rendering: auto;
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: pixelated;
image-rendering: crisp-edges;
}
.gloss-image-link[data-image-rendering=crisp-edges] .gloss-image,
.gloss-image-link[data-image-rendering=crisp-edges] .gloss-image-background {
.gloss-image-link[data-image-rendering=crisp-edges] .gloss-image {
image-rendering: auto;
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: crisp-edges;
}
:root[data-browser=firefox] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image,
:root[data-browser=firefox] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image-background,
:root[data-browser=firefox-mobile] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image,
:root[data-browser=firefox-mobile] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image-background {
:root[data-browser=firefox-mobile] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image {
image-rendering: auto;
}
.gloss-image-link[data-has-aspect-ratio=true] .gloss-image-sizer {
Expand All @@ -131,26 +101,9 @@
vertical-align: top;
font-size: 0;
}
.gloss-image-link-text {
display: none;
line-height: var(--line-height);
}
.gloss-image-link-text::before {
content: '[';
}
.gloss-image-link-text::after {
content: ']';
}
.gloss-image-description {
display: block;
white-space: pre-line;
}

.gloss-image-link[data-appearance=monochrome] .gloss-image {
opacity: 0;
}
.gloss-image-link:not([data-appearance=monochrome]) .gloss-image-background {
display: none;
filter: grayscale(1);
}

.gloss-image-link[data-size-units=em] .gloss-image-container {
Expand Down Expand Up @@ -189,14 +142,6 @@
:root[data-glossary-layout-mode=compact] .gloss-image-link[data-collapsible=true]:focus .gloss-image-container {
display: block;
}
.gloss-image-link[data-collapsed=true] .gloss-image-link-text,
:root[data-glossary-layout-mode=compact] .gloss-image-link[data-collapsible=true] .gloss-image-link-text {
display: inline;
}
.gloss-image-link[data-collapsed=true]~.gloss-image-description,
:root[data-glossary-layout-mode=compact] .gloss-image-description {
display: inline;
}


/* Links */
Expand Down
6 changes: 6 additions & 0 deletions ext/js/background/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ export class Backend {
['getDictionaryInfo', this._onApiGetDictionaryInfo.bind(this)],
['purgeDatabase', this._onApiPurgeDatabase.bind(this)],
['getMedia', this._onApiGetMedia.bind(this)],
['getMediaObjects', this._onApiGetMediaObjects.bind(this)],
['logGenericErrorBackend', this._onApiLogGenericErrorBackend.bind(this)],
['logIndicatorClear', this._onApiLogIndicatorClear.bind(this)],
['modifySettings', this._onApiModifySettings.bind(this)],
Expand Down Expand Up @@ -795,6 +796,11 @@ export class Backend {
return await this._getNormalizedDictionaryDatabaseMedia(targets);
}

/** @type {import('api').ApiHandler<'getMediaObjects'>} */
async _onApiGetMediaObjects({targets}) {
return await this._dictionaryDatabase.getMediaObjects(targets);
}

/** @type {import('api').ApiHandler<'logGenericErrorBackend'>} */
_onApiLogGenericErrorBackend({error, level, context}) {
log.logGenericError(ExtensionError.deserialize(error), level, context);
Expand Down
12 changes: 12 additions & 0 deletions ext/js/background/offscreen-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import {base64ToArrayBuffer} from '../data/array-buffer-util.js';
* The background service workers doesn't have access a webpage to read the clipboard from,
* so it must be done in the offscreen page.
*
* - Provide access to `URL.createObjectURL` so that we can load media as blobs directly on the
* backend, which performs better than sending the media as base64 strings to the frontend.
*
* - Provide a longer lifetime for the dictionary database. The background service worker can be
* terminated by the web browser, which means that when it restarts, it has to go through its
* initialization process again. This initialization process can take a non-trivial amount of
Expand Down Expand Up @@ -173,6 +176,15 @@ export class DictionaryDatabaseProxy {
const serializedMedia = /** @type {import('dictionary-database').Media<string>[]} */ (await this._offscreen.sendMessagePromise({action: 'databaseGetMediaOffscreen', params: {targets}}));
return serializedMedia.map((m) => ({...m, content: base64ToArrayBuffer(m.content)}));
}

/**
* @param {import('dictionary-database').MediaRequest[]} targets
* @returns {Promise<import('dictionary-database').MediaObject[]>}
*/
async getMediaObjects(targets) {
console.log('offscreen getMediaObjects', targets);
return await this._offscreen.sendMessagePromise({action: 'databaseGetMediaObjectsOffscreen', params: {targets}});
}
}

export class TranslatorProxy {
Expand Down
6 changes: 6 additions & 0 deletions ext/js/background/offscreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export class Offscreen {
['getDictionaryInfoOffscreen', this._getDictionaryInfoHandler.bind(this)],
['databasePurgeOffscreen', this._purgeDatabaseHandler.bind(this)],
['databaseGetMediaOffscreen', this._getMediaHandler.bind(this)],
['databaseGetMediaObjectsOffscreen', this._getMediaObjectsHandler.bind(this)],
['translatorPrepareOffscreen', this._prepareTranslatorHandler.bind(this)],
['findKanjiOffscreen', this._findKanjiHandler.bind(this)],
['findTermsOffscreen', this._findTermsHandler.bind(this)],
Expand Down Expand Up @@ -110,6 +111,11 @@ export class Offscreen {
return media.map((m) => ({...m, content: arrayBufferToBase64(m.content)}));
}

/** @type {import('offscreen').ApiHandler<'databaseGetMediaObjectsOffscreen'>} */
async _getMediaObjectsHandler({targets}) {
return await this._dictionaryDatabase.getMediaObjects(targets);
}

/** @type {import('offscreen').ApiHandler<'translatorPrepareOffscreen'>} */
_prepareTranslatorHandler() {
this._translator.prepare();
Expand Down
9 changes: 9 additions & 0 deletions ext/js/comm/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,15 @@ export class API {
return this._invoke('getMedia', {targets});
}

/**
* @param {import('api').ApiParam<'getMediaObjects', 'targets'>} targets
* @returns {Promise<import('api').ApiReturn<'getMediaObjects'>>}
*/
getMediaObjects(targets) {
console.log('getMediaObjects', targets);
return this._invoke('getMediaObjects', {targets});
}

/**
* @param {import('api').ApiParam<'logGenericErrorBackend', 'error'>} error
* @param {import('api').ApiParam<'logGenericErrorBackend', 'level'>} level
Expand Down
15 changes: 15 additions & 0 deletions ext/js/dictionary/dictionary-database.js
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,21 @@ export class DictionaryDatabase {
return this._findMultiBulk('media', ['path'], items, this._createOnlyQuery4, predicate, this._createMediaBind);
}

/**
* This requires the ability to call URL.createObjectURL, which is not available in a service worker. Therefore Chrome must go through the Offscreen API as opposed to directly calling this.
* @param {import('dictionary-database').MediaRequest[]} items
* @returns {Promise<import('dictionary-database').MediaObject[]>}
*/
async getMediaObjects(items) {
/** @type {import('dictionary-database').FindPredicate<import('dictionary-database').MediaRequest, import('dictionary-database').MediaDataArrayBufferContent>} */
const predicate = (row, item) => (row.dictionary === item.dictionary);
return (await this._findMultiBulk('media', ['path'], items, this._createOnlyQuery4, predicate, this._createMediaBind)).map((m) => {
const blob = new Blob([m.content], {type: m.mediaType});
const url = URL.createObjectURL(blob);
return {...m, content: null, url};
});
}

/**
* @returns {Promise<import('dictionary-importer').Summary[]>}
*/
Expand Down
Loading

0 comments on commit b0837a3

Please sign in to comment.