Skip to content

Commit 34aada5

Browse files
committed
Read Aloud: Expose segment generation/annotation for mobile
#215 (comment)
1 parent 9bf81bd commit 34aada5

3 files changed

Lines changed: 114 additions & 10 deletions

File tree

src/common/view.js

Lines changed: 88 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { getCurrentColorScheme } from './lib/utilities';
88
import pako from 'pako';
99
import { createPositionMapper } from './sdt/create-position-mapper';
1010
import { getTextNodeSpans } from './sdt/position-mapper';
11+
import { buildSDTReadAloudSegments, getSDTLang } from './read-aloud/sdt-segments';
1112
import {
1213
openStructuredDocumentTextPack,
1314
SDT_PACK_VERSION,
@@ -435,6 +436,92 @@ class View {
435436
if (!sdt) {
436437
return null;
437438
}
439+
let built = this._buildAnnotationFromSDT(sdt, sdtAnchor, type);
440+
if (!built) {
441+
return null;
442+
}
443+
return this._annotationManager.addAnnotation({
444+
type,
445+
color,
446+
comment,
447+
tags,
448+
position: built.position,
449+
text: built.text,
450+
sortIndex: built.sortIndex,
451+
pageLabel: built.pageLabel,
452+
});
453+
}
454+
455+
/**
456+
* @param {ReadAloudGranularity} granularity
457+
* @returns {Promise<ReadAloudSegment[] | null>}
458+
*/
459+
async getReadAloudSegments(granularity) {
460+
let sdt = await this._loadSDT();
461+
if (!sdt) {
462+
return null;
463+
}
464+
let lang = getSDTLang(sdt.structure);
465+
let { segments } = buildSDTReadAloudSegments(sdt.structure, granularity, lang);
466+
return segments;
467+
}
468+
469+
/**
470+
* @param {string} [id] If set, resize an existing annotation
471+
* @param {SDTPosition} startPosition
472+
* @param {SDTPosition} [endPosition] Defaults to startPosition
473+
* @param {AnnotationType} type
474+
* @param {string} color
475+
* @param {string} [comment]
476+
* @param {string[]} [tags]
477+
* @returns {Promise<import('./types').Annotation | null>}
478+
*/
479+
async setReadAloudAnnotation({ id, startPosition, endPosition, type, color, comment, tags }) {
480+
let sdt = await this._loadSDT();
481+
if (!sdt) {
482+
return null;
483+
}
484+
let sdtAnchor = {
485+
start: startPosition.start,
486+
end: (endPosition || startPosition).end,
487+
};
488+
let built = this._buildAnnotationFromSDT(sdt, sdtAnchor, type);
489+
if (!built) {
490+
return null;
491+
}
492+
if (id && this._annotationManager._getAnnotationByID(id)) {
493+
let update = {
494+
id,
495+
position: built.position,
496+
sortIndex: built.sortIndex,
497+
pageLabel: built.pageLabel,
498+
text: built.text,
499+
};
500+
// Only overwrite type/color when explicitly provided, so a resize
501+
// preserves them
502+
if (type) {
503+
update.type = type;
504+
}
505+
if (color) {
506+
update.color = color;
507+
}
508+
this._annotationManager.updateAnnotations([update]);
509+
return this._annotationManager._getAnnotationByID(id);
510+
}
511+
return this._annotationManager.addAnnotation({
512+
type,
513+
color,
514+
comment,
515+
tags,
516+
position: built.position,
517+
text: built.text,
518+
sortIndex: built.sortIndex,
519+
pageLabel: built.pageLabel,
520+
});
521+
}
522+
523+
// Map an SDT range to a source position, sortIndex/pageLabel, and text.
524+
_buildAnnotationFromSDT(sdt, sdtAnchor, type) {
438525
let spans = getTextNodeSpans(sdt.structure, sdtAnchor);
439526
let position = sdt.mapper.textNodeSpansToSourcePosition(spans);
440527
if (!position) {
@@ -448,16 +535,7 @@ class View {
448535
return null;
449536
}
450537
let text = spans.map(s => s.node.text.slice(s.start, s.end)).join('');
451-
return this._annotationManager.addAnnotation({
452-
type,
453-
color,
454-
comment,
455-
tags,
456-
position,
457-
text,
458-
sortIndex: meta.sortIndex,
459-
pageLabel: meta.pageLabel,
460-
});
538+
return { position, text, sortIndex: meta.sortIndex, pageLabel: meta.pageLabel };
461539
}
462540
}
463541

src/index.android.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,19 @@ window.createAnnotationFromSDT = async (options) => {
185185
postMessage('onCreateAnnotationFromSDT', { requestID: options.requestID, annotation });
186186
};
187187

188+
window.getReadAloudSegments = async (options) => {
189+
log("Get Read Aloud segments: " + options.granularity);
190+
const segments = await window._view.getReadAloudSegments(options.granularity);
191+
postMessage('onReadAloudSegments', { requestID: options.requestID, segments });
192+
};
193+
194+
window.setReadAloudAnnotation = async (options) => {
195+
const params = JSON.parse(decodeBase64(options.params));
196+
log("Set Read Aloud annotation: " + params.type);
197+
const annotation = await window._view.setReadAloudAnnotation(params);
198+
postMessage('onReadAloudAnnotation', { requestID: options.requestID, annotation });
199+
};
200+
188201
window.setPageLabels = (options) => {
189202
const pageLabels = JSON.parse(decodeBase64(options.pageLabels));
190203
log("Set page labels: " + JSON.stringify(pageLabels));

src/index.ios.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,5 +154,18 @@ window.createAnnotationFromSDT = async (options) => {
154154
postMessage('onCreateAnnotationFromSDT', { requestID: options.requestID, annotation });
155155
};
156156

157+
window.getReadAloudSegments = async (options) => {
158+
log("Get Read Aloud segments: " + options.granularity);
159+
const segments = await window._view.getReadAloudSegments(options.granularity);
160+
postMessage('onReadAloudSegments', { requestID: options.requestID, segments });
161+
};
162+
163+
window.setReadAloudAnnotation = async (options) => {
164+
const params = JSON.parse(decodeBase64(options.params));
165+
log("Set Read Aloud annotation: " + params.type);
166+
const annotation = await window._view.setReadAloudAnnotation(params);
167+
postMessage('onReadAloudAnnotation', { requestID: options.requestID, annotation });
168+
};
169+
157170
// Notify when iframe is loaded
158171
postMessage('onInitialized');

0 commit comments

Comments
 (0)