waha-shared 1.0.307 → 1.0.309
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data/bibleStatuses/bibleStatuses.json +31 -310
- package/dist/data/bibleTexts/bibleTexts.json +6 -4
- package/dist/data/curriculumOnboarding/curriculumOnboarding.json +34 -0
- package/dist/data/curriculumOnboarding/curriculumOnboarding.schema.json +38 -0
- package/dist/data/curriculumOnboarding/curriculumOnboarding.zod.d.ts +11 -0
- package/dist/data/curriculumOnboarding/curriculumOnboarding.zod.js +18 -0
- package/dist/data/curriculumOnboarding/index.d.ts +9 -0
- package/dist/data/curriculumOnboarding/index.js +7 -0
- package/dist/data/dblAudioLicenses/dblAudioLicenses.json +415 -415
- package/dist/data/dblTextLicenses/dblTextLicenses.json +1248 -1158
- package/dist/data/languages/index.d.ts +2 -0
- package/dist/data/languages/languages.json +313 -3
- package/dist/data/languages/languages.schema.json +9 -1
- package/dist/data/languages/languages.zod.d.ts +3 -0
- package/dist/data/languages/languages.zod.js +7 -0
- package/dist/data/mediaDurations/mediaDurations.json +107 -110
- package/dist/data/releaseNotes/releaseNotes.json +47 -3
- package/dist/data/translationsApp/index.d.ts +1 -1
- package/dist/data/translationsApp/translationsApp.schema.json +2 -1
- package/dist/data/translationsApp/translationsApp.zod.d.ts +2 -2
- package/dist/data/translationsApp/translationsApp.zod.js +1 -1
- package/dist/data/translationsSet/translationsSet.json +192 -192
- package/dist/functions/bibles.d.ts +11 -8
- package/dist/functions/bibles.js +34 -11
- package/dist/functions/languages.js +7 -0
- package/dist/functions/scripturePassages.d.ts +26 -5
- package/dist/functions/scripturePassages.js +92 -41
- package/dist/functions/sets.js +3 -1
- package/dist/types/languages.d.ts +9 -0
- package/dist/types/scripturePassages.d.ts +0 -1
- package/dist/types/scripturePassages.js +0 -1
- package/dist/types/sets.d.ts +7 -0
- package/package.json +1 -1
package/dist/functions/bibles.js
CHANGED
|
@@ -32,15 +32,19 @@ function getBibleInfo(bibleId) {
|
|
|
32
32
|
t.bibleAudioId === bibleText?.bibleTextId);
|
|
33
33
|
const language = languages_1.languages.find((l) => l.languageId === bibleText?.languageId);
|
|
34
34
|
const script = scripts_1.scripts.find((s) => s.name === language?.script) ?? scripts_1.scripts[0];
|
|
35
|
+
if (!bibleText || !bibleAudio || !language)
|
|
36
|
+
return;
|
|
37
|
+
const availableChapters = getAvailableChapters(bibleText.bibleTextId);
|
|
35
38
|
const result = bibleText && bibleAudio && language
|
|
36
39
|
? {
|
|
37
40
|
...bibleText,
|
|
38
41
|
...bibleAudio,
|
|
39
42
|
language,
|
|
40
43
|
script,
|
|
41
|
-
availableTextChapters:
|
|
42
|
-
availableAudioChapters:
|
|
43
|
-
availableTimingsChapters:
|
|
44
|
+
availableTextChapters: availableChapters.text,
|
|
45
|
+
availableAudioChapters: availableChapters.audio,
|
|
46
|
+
availableTimingsChapters: availableChapters.timings,
|
|
47
|
+
availableChapters: availableChapters.all,
|
|
44
48
|
bookNames: {
|
|
45
49
|
...(bibleText.bookNameFallback
|
|
46
50
|
? (bibleStatuses_1.bibleStatuses[bibleText.bookNameFallback]?.bookNames ?? {})
|
|
@@ -177,19 +181,16 @@ const bookLengths = new Map([
|
|
|
177
181
|
['REV', 22],
|
|
178
182
|
]);
|
|
179
183
|
/**
|
|
180
|
-
* Expands an optimized chapter list back to individual chapters
|
|
181
|
-
* names (e.g., "GEN") back to all chapters (e.g., ["GEN.1",
|
|
182
|
-
* Converts testament names ("OT", "NT") back to all chapters
|
|
183
|
-
* Leaves individual chapters unchanged
|
|
184
|
+
* Expands an optimized chapter list back to individual chapters for a single
|
|
185
|
+
* type. Converts book names (e.g., "GEN") back to all chapters (e.g., ["GEN.1",
|
|
186
|
+
* "GEN.2", ..."]). Converts testament names ("OT", "NT") back to all chapters
|
|
187
|
+
* in that testament. Leaves individual chapters unchanged.
|
|
184
188
|
*
|
|
185
189
|
* @param optimizedChapters - Array that may contain testament IDs, book IDs, or
|
|
186
190
|
* chapter IDs
|
|
187
191
|
* @returns Array of individual chapter IDs in canonical order
|
|
188
192
|
*/
|
|
189
|
-
function
|
|
190
|
-
if (!bibleId)
|
|
191
|
-
return [];
|
|
192
|
-
const optimizedChapters = bibleStatuses_1.bibleStatuses[bibleId]?.[type] || [];
|
|
193
|
+
function expandOptimizedChapters(optimizedChapters) {
|
|
193
194
|
if (optimizedChapters.length === 0)
|
|
194
195
|
return [];
|
|
195
196
|
// Build a Set of included items for O(1) lookup
|
|
@@ -236,6 +237,28 @@ function getAvailableChapters(bibleId, type) {
|
|
|
236
237
|
}
|
|
237
238
|
return result;
|
|
238
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* Returns available chapters for all types (text, audio, timings) plus a
|
|
242
|
+
* combined `all` array.
|
|
243
|
+
*
|
|
244
|
+
* @param bibleId - The bible translation ID to look up
|
|
245
|
+
* @returns Object with expanded chapter arrays for each type and a combined
|
|
246
|
+
* `all` array
|
|
247
|
+
*/
|
|
248
|
+
function getAvailableChapters(bibleId) {
|
|
249
|
+
const emptyReturn = { text: [], audio: [], timings: [], all: [] };
|
|
250
|
+
if (!bibleId)
|
|
251
|
+
return emptyReturn;
|
|
252
|
+
const status = bibleStatuses_1.bibleStatuses[bibleId];
|
|
253
|
+
if (!status)
|
|
254
|
+
return emptyReturn;
|
|
255
|
+
const text = expandOptimizedChapters(status.text ?? []);
|
|
256
|
+
const audio = expandOptimizedChapters(status.audio ?? []);
|
|
257
|
+
const timings = expandOptimizedChapters(status.timings ?? []);
|
|
258
|
+
const allSet = new Set([...text, ...audio, ...timings]);
|
|
259
|
+
const all = bibleChaptersList_1.bibleChaptersList.filter((c) => allSet.has(c));
|
|
260
|
+
return { text, audio, timings, all };
|
|
261
|
+
}
|
|
239
262
|
function getPercentage(bibleId, type) {
|
|
240
263
|
const optimizedChapters = bibleStatuses_1.bibleStatuses[bibleId]?.[type] || [];
|
|
241
264
|
let total = 0;
|
|
@@ -9,6 +9,7 @@ exports.getMeetTranslations = getMeetTranslations;
|
|
|
9
9
|
const bibleAudios_1 = require("../data/bibleAudios");
|
|
10
10
|
const bibleTexts_1 = require("../data/bibleTexts");
|
|
11
11
|
const curriculumFoundations_1 = require("../data/curriculumFoundations");
|
|
12
|
+
const curriculumOnboarding_1 = require("../data/curriculumOnboarding");
|
|
12
13
|
const curriculumQuestions_1 = require("../data/curriculumQuestions");
|
|
13
14
|
const curriculumTopics_1 = require("../data/curriculumTopics");
|
|
14
15
|
const languages_1 = require("../data/languages");
|
|
@@ -35,6 +36,7 @@ function getLanguageInfo(languageId, options) {
|
|
|
35
36
|
availableTextChapters: [],
|
|
36
37
|
availableAudioChapters: [],
|
|
37
38
|
availableTimingsChapters: [],
|
|
39
|
+
availableChapters: [],
|
|
38
40
|
language: languages_1.languages[0],
|
|
39
41
|
fullCopyright: '',
|
|
40
42
|
bookNames: {},
|
|
@@ -48,10 +50,12 @@ function getLanguageInfo(languageId, options) {
|
|
|
48
50
|
trainingVideos: 'eng',
|
|
49
51
|
questionAudio: 'eng',
|
|
50
52
|
questionText: 'eng',
|
|
53
|
+
onboardingPassages: 'eng',
|
|
51
54
|
},
|
|
52
55
|
script: scripts_1.scripts[0],
|
|
53
56
|
lessonPauses: lessonPauses_1.lessonPauses,
|
|
54
57
|
allBibleIds: [],
|
|
58
|
+
onboardingPassageIds: curriculumOnboarding_1.curriculumOnboarding[0].passages,
|
|
55
59
|
};
|
|
56
60
|
const language = languages_1.languages.find((language) => language.languageId === languageId);
|
|
57
61
|
if (!language) {
|
|
@@ -66,6 +70,7 @@ function getLanguageInfo(languageId, options) {
|
|
|
66
70
|
const questionsCurriculum = curriculumQuestions_1.curriculumQuestions.find((questionCurriculum) => questionCurriculum.curriculumId === language.curriculum.questions);
|
|
67
71
|
const foundationsCurriculum = curriculumFoundations_1.curriculumFoundations.find((foundationsCurriculum) => foundationsCurriculum.curriculumId === language.curriculum.foundations);
|
|
68
72
|
const topicsCurriculum = curriculumTopics_1.curriculumTopics.find((topicsCurriculum) => topicsCurriculum.curriculumId === language?.curriculum.topics);
|
|
73
|
+
const onboardingCurriculum = curriculumOnboarding_1.curriculumOnboarding.find((onboardingCurriculum) => onboardingCurriculum.curriculumId === language.curriculum.onboarding);
|
|
69
74
|
const setIds = [];
|
|
70
75
|
if (foundationsCurriculum)
|
|
71
76
|
setIds.push(...foundationsCurriculum.sets);
|
|
@@ -101,10 +106,12 @@ function getLanguageInfo(languageId, options) {
|
|
|
101
106
|
titles: language.bridgeLanguages?.titles ?? language.languageId,
|
|
102
107
|
questionAudio: language.bridgeLanguages?.questionAudio ?? language.languageId,
|
|
103
108
|
questionText: language.bridgeLanguages?.questionText ?? language.languageId,
|
|
109
|
+
onboardingPassages: language.bridgeLanguages?.onboardingPassages ?? language.languageId,
|
|
104
110
|
},
|
|
105
111
|
script,
|
|
106
112
|
lessonPauses: lessonPauses_1.lessonPauses,
|
|
107
113
|
allBibleIds: (0, bibles_1.getAllBibleIds)(language),
|
|
114
|
+
onboardingPassageIds: onboardingCurriculum?.passages ?? defaultReturn.onboardingPassageIds,
|
|
108
115
|
};
|
|
109
116
|
return toReturn;
|
|
110
117
|
}
|
|
@@ -28,8 +28,29 @@ export declare function getPassagesString(passages: Array<{
|
|
|
28
28
|
export interface GetChapterParams {
|
|
29
29
|
chapterId: string;
|
|
30
30
|
bibleId: string;
|
|
31
|
+
noTextAvailableString: string;
|
|
31
32
|
}
|
|
32
33
|
export type GetChapter = (params: GetChapterParams) => Promise<BibleChapter | undefined>;
|
|
34
|
+
/**
|
|
35
|
+
* Raw chapter fetcher — returns whatever the backing store has, with no
|
|
36
|
+
* placeholder synthesis or post-processing.
|
|
37
|
+
*/
|
|
38
|
+
export type RawChapterFetcher = (params: {
|
|
39
|
+
bibleId: string;
|
|
40
|
+
chapterId: string;
|
|
41
|
+
}) => Promise<BibleChapter | undefined>;
|
|
42
|
+
/**
|
|
43
|
+
* Wraps a raw chapter fetcher with placeholder logic shared across all
|
|
44
|
+
* backends:
|
|
45
|
+
*
|
|
46
|
+
* - If the chapter is not in `availableTextChapters` nor
|
|
47
|
+
* `availableTimingsChapters`, synthesize a one-verse placeholder without
|
|
48
|
+
* calling the underlying fetcher.
|
|
49
|
+
* - If a fetched chapter is timings-only (verses exist but none have text), patch
|
|
50
|
+
* verse 1's text with `noTextAvailableString` so downstream consumers can
|
|
51
|
+
* render something.
|
|
52
|
+
*/
|
|
53
|
+
export declare function withChapterPlaceholders(fetchRaw: RawChapterFetcher): GetChapter;
|
|
33
54
|
interface GetScripturePassageParams {
|
|
34
55
|
bibleId: string;
|
|
35
56
|
passageId: string;
|
|
@@ -37,13 +58,13 @@ interface GetScripturePassageParams {
|
|
|
37
58
|
noTextAvailableString: string;
|
|
38
59
|
}
|
|
39
60
|
/** Gets a scripture passage by extracting verses from chapters documents. */
|
|
40
|
-
export declare function getScripturePassage({ bibleId, passageId, getChapter, noTextAvailableString, }: GetScripturePassageParams): Promise<ScripturePassage>;
|
|
61
|
+
export declare function getScripturePassage({ bibleId, passageId, getChapter, noTextAvailableString, }: GetScripturePassageParams): Promise<ScripturePassage | undefined>;
|
|
41
62
|
/** Gets all scripture passages for a lesson. */
|
|
42
63
|
export declare function getLessonScripture({ getChapter, lessonInfo, noTextAvailableString, }: {
|
|
43
64
|
lessonInfo: LessonInfo;
|
|
44
65
|
getChapter: (params: GetChapterParams) => Promise<BibleChapter | undefined>;
|
|
45
66
|
noTextAvailableString: string;
|
|
46
|
-
}): Promise<Array<ScripturePassage>>;
|
|
67
|
+
}): Promise<Array<ScripturePassage | undefined>>;
|
|
47
68
|
/**
|
|
48
69
|
* Converts a verse number to a superscript string. This is useful for
|
|
49
70
|
* displaying verse numbers in a more visually appealing way. For example, "1"
|
|
@@ -63,13 +84,13 @@ export declare function getFtbDuration(section: Section, lessonInfo: DbsInfo | V
|
|
|
63
84
|
* sections) by accumulating forward through the lesson. After this, every
|
|
64
85
|
* section has both fields set.
|
|
65
86
|
*/
|
|
66
|
-
export declare function enrichSections(lessonInfo: DbsInfo | VideoInfo, scripture: Array<ScripturePassage>): EnrichedSection[];
|
|
87
|
+
export declare function enrichSections(lessonInfo: DbsInfo | VideoInfo, scripture: Array<ScripturePassage | undefined>): EnrichedSection[];
|
|
67
88
|
/**
|
|
68
89
|
* Converts verse timings from chapter-relative to lesson-relative using each
|
|
69
90
|
* section's `startTime` (set by {@link enrichSections}).
|
|
70
91
|
*/
|
|
71
92
|
export declare function normalizeVerseTimings({ enrichedSections, scripture, lessonInfo, }: {
|
|
72
93
|
enrichedSections: EnrichedSection[];
|
|
73
|
-
scripture: Array<ScripturePassage>;
|
|
94
|
+
scripture: Array<ScripturePassage | undefined>;
|
|
74
95
|
lessonInfo: DbsInfo | VideoInfo;
|
|
75
|
-
}): Array<ScripturePassage>;
|
|
96
|
+
}): Array<ScripturePassage | undefined>;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.parseVerseRange = void 0;
|
|
4
4
|
exports.getChapterUrl = getChapterUrl;
|
|
5
5
|
exports.getPassagesString = getPassagesString;
|
|
6
|
+
exports.withChapterPlaceholders = withChapterPlaceholders;
|
|
6
7
|
exports.getScripturePassage = getScripturePassage;
|
|
7
8
|
exports.getLessonScripture = getLessonScripture;
|
|
8
9
|
exports.verseToSuperscript = verseToSuperscript;
|
|
@@ -79,49 +80,78 @@ function getPassagesString(passages) {
|
|
|
79
80
|
}
|
|
80
81
|
return parts.join(', ');
|
|
81
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Wraps a raw chapter fetcher with placeholder logic shared across all
|
|
85
|
+
* backends:
|
|
86
|
+
*
|
|
87
|
+
* - If the chapter is not in `availableTextChapters` nor
|
|
88
|
+
* `availableTimingsChapters`, synthesize a one-verse placeholder without
|
|
89
|
+
* calling the underlying fetcher.
|
|
90
|
+
* - If a fetched chapter is timings-only (verses exist but none have text), patch
|
|
91
|
+
* verse 1's text with `noTextAvailableString` so downstream consumers can
|
|
92
|
+
* render something.
|
|
93
|
+
*/
|
|
94
|
+
function withChapterPlaceholders(fetchRaw) {
|
|
95
|
+
return async ({ bibleId, chapterId, noTextAvailableString }) => {
|
|
96
|
+
const bibleInfo = (0, bibles_1.getBibleInfo)(bibleId);
|
|
97
|
+
if (!bibleInfo)
|
|
98
|
+
return undefined;
|
|
99
|
+
if (!bibleInfo.availableTextChapters.includes(chapterId) &&
|
|
100
|
+
!bibleInfo.availableTimingsChapters.includes(chapterId)) {
|
|
101
|
+
return {
|
|
102
|
+
bookName: bibleInfo.bookNames[chapterId.split('.')[0]],
|
|
103
|
+
chapterId,
|
|
104
|
+
reference: chapterId,
|
|
105
|
+
titles: null,
|
|
106
|
+
translationId: bibleId,
|
|
107
|
+
verses: [{ text: noTextAvailableString, verseId: `${chapterId}.1` }],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const chapter = await fetchRaw({ bibleId, chapterId });
|
|
111
|
+
if (!chapter)
|
|
112
|
+
return undefined;
|
|
113
|
+
if (chapter.verses.length > 0 && !chapter.verses.some((v) => v.text)) {
|
|
114
|
+
chapter.verses[0].text = noTextAvailableString;
|
|
115
|
+
}
|
|
116
|
+
return chapter;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
82
119
|
/** Gets a scripture passage by extracting verses from chapters documents. */
|
|
83
120
|
async function getScripturePassage({ bibleId, passageId, getChapter, noTextAvailableString, }) {
|
|
84
121
|
const bibleInfo = (0, bibles_1.getBibleInfo)(bibleId);
|
|
85
122
|
const { startVerse, endVerse, chapterId } = (0, bibleBooks_1.parseVerseRange)(passageId);
|
|
86
|
-
const noTextAvailableReturn = {
|
|
87
|
-
bibleId,
|
|
88
|
-
header: getPassagesString([{ passageId, bibleId }]),
|
|
89
|
-
passageId,
|
|
90
|
-
verses: [],
|
|
91
|
-
};
|
|
92
123
|
if (!bibleInfo)
|
|
93
|
-
return
|
|
94
|
-
const returnExpected = bibleInfo.availableTextChapters.includes(chapterId) ||
|
|
95
|
-
bibleInfo.availableTimingsChapters.includes(chapterId);
|
|
96
|
-
/**
|
|
97
|
-
* In this case, we know the bible does not have text for this chapter, so the
|
|
98
|
-
* user will see a placeholder verse.
|
|
99
|
-
*/
|
|
100
|
-
if (!returnExpected) {
|
|
101
|
-
noTextAvailableReturn.verses = [
|
|
102
|
-
{ text: noTextAvailableString, verseId: '' },
|
|
103
|
-
];
|
|
104
|
-
return noTextAvailableReturn;
|
|
105
|
-
}
|
|
124
|
+
return;
|
|
106
125
|
try {
|
|
107
126
|
const startVerseNum = parseInt(startVerse);
|
|
108
127
|
const endVerseNum = parseInt(endVerse);
|
|
109
|
-
const chapter = await getChapter({
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return
|
|
128
|
+
const chapter = await getChapter({
|
|
129
|
+
chapterId,
|
|
130
|
+
bibleId,
|
|
131
|
+
noTextAvailableString,
|
|
132
|
+
});
|
|
133
|
+
if (!chapter || chapter.verses.length === 0)
|
|
134
|
+
return;
|
|
135
|
+
/**
|
|
136
|
+
* If we only have one verse for a chapter, it is the placeholder verse and
|
|
137
|
+
* we should return them as is instead of trying to extract a passage.
|
|
138
|
+
*/
|
|
139
|
+
if (chapter.verses.length === 1) {
|
|
140
|
+
return {
|
|
141
|
+
passageId,
|
|
142
|
+
bibleId: chapter.translationId,
|
|
143
|
+
verses: chapter.verses,
|
|
144
|
+
};
|
|
116
145
|
}
|
|
117
|
-
|
|
146
|
+
const verses = extractVersesFromChapter(chapter, startVerseNum, endVerseNum);
|
|
147
|
+
/**
|
|
148
|
+
* For textless chapters, verse 1 is always the placeholder verse. After
|
|
149
|
+
* extraction, we may have lost verse 1, so we patch back in the placeholder
|
|
150
|
+
* text.
|
|
151
|
+
*/
|
|
152
|
+
if (!verses.some((v) => v.text) && verses.length > 0)
|
|
118
153
|
verses[0].text = noTextAvailableString;
|
|
119
|
-
return {
|
|
120
|
-
passageId,
|
|
121
|
-
bibleId: chapter.translationId,
|
|
122
|
-
header: getPassagesString([{ passageId, bibleId }]),
|
|
123
|
-
verses,
|
|
124
|
-
};
|
|
154
|
+
return { passageId, bibleId: chapter.translationId, verses };
|
|
125
155
|
}
|
|
126
156
|
catch (error) {
|
|
127
157
|
console.error(`Error getting scripture passage ${passageId} in ${bibleId}`, error);
|
|
@@ -196,16 +226,23 @@ function getFtbDuration(section, lessonInfo) {
|
|
|
196
226
|
*/
|
|
197
227
|
function enrichSections(lessonInfo, scripture) {
|
|
198
228
|
const storySections = lessonInfo.sections.filter((s) => s.chapter === sets_1.Chapter.STORY);
|
|
199
|
-
|
|
200
|
-
|
|
229
|
+
/**
|
|
230
|
+
* Forward pass: compute lengths and start times for all non-application
|
|
231
|
+
* sections. We track whether any prior story had an unknown length — once
|
|
232
|
+
* that happens, every later story's startTime is unreliable (it accumulates
|
|
233
|
+
* from a bogus length), so we flag it with `ignoreTimings`.
|
|
234
|
+
*/
|
|
201
235
|
let currentTime = 0;
|
|
236
|
+
let priorStoryLengthUnknown = false;
|
|
202
237
|
const enriched = lessonInfo.sections.map((section) => {
|
|
203
238
|
if (!section.chapter)
|
|
204
239
|
return { ...section, startTime: 0, length: 0 };
|
|
205
240
|
currentTime += section.pauseBefore ?? 0;
|
|
206
241
|
let length;
|
|
242
|
+
const isStory = section.chapter === sets_1.Chapter.STORY;
|
|
243
|
+
const ignoreTimings = isStory && priorStoryLengthUnknown ? true : undefined;
|
|
207
244
|
const startTime = currentTime;
|
|
208
|
-
if (
|
|
245
|
+
if (!isStory) {
|
|
209
246
|
length = mediaDurations_1.mediaDurations[section.languageId]?.[section.fileName];
|
|
210
247
|
}
|
|
211
248
|
else {
|
|
@@ -222,12 +259,14 @@ function enrichSections(lessonInfo, scripture) {
|
|
|
222
259
|
}
|
|
223
260
|
}
|
|
224
261
|
}
|
|
262
|
+
if (length == null)
|
|
263
|
+
priorStoryLengthUnknown = true;
|
|
225
264
|
}
|
|
226
265
|
if (length == null) {
|
|
227
266
|
console.warn(`Missing duration for section ${section.id} (${section.chapter}, ${section.fileName})`);
|
|
228
267
|
}
|
|
229
268
|
currentTime += length ?? 0;
|
|
230
|
-
return { ...section, length: length ?? 0, startTime };
|
|
269
|
+
return { ...section, length: length ?? 0, startTime, ignoreTimings };
|
|
231
270
|
});
|
|
232
271
|
// Backward pass: compute application section start times from the end of the
|
|
233
272
|
// lesson file, so they are always correct even if story durations are
|
|
@@ -254,12 +293,24 @@ function enrichSections(lessonInfo, scripture) {
|
|
|
254
293
|
function normalizeVerseTimings({ enrichedSections, scripture, lessonInfo, }) {
|
|
255
294
|
const storySections = enrichedSections.filter((s) => s.chapter === sets_1.Chapter.STORY);
|
|
256
295
|
return scripture.map((passage, passageIndex) => {
|
|
296
|
+
if (!passage)
|
|
297
|
+
return undefined;
|
|
257
298
|
const section = storySections[passageIndex];
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
299
|
+
const ignoreTimingsReturn = {
|
|
300
|
+
...passage,
|
|
301
|
+
verses: passage.verses.map((verse) => ({ ...verse, timings: null })),
|
|
302
|
+
};
|
|
303
|
+
/**
|
|
304
|
+
* Section's startTime is wrong (e.g. an earlier story's scripture hasn't
|
|
305
|
+
* loaded), so applying it as an offset would produce bogus lesson-relative
|
|
306
|
+
* timings. Strip verse timings instead, which disables karaoke until the
|
|
307
|
+
* section becomes trusted.
|
|
308
|
+
*/
|
|
309
|
+
if (section.ignoreTimings)
|
|
310
|
+
return ignoreTimingsReturn;
|
|
311
|
+
const firstTimedVerse = passage?.verses.find((v) => v.timings);
|
|
261
312
|
if (!firstTimedVerse?.timings)
|
|
262
|
-
return
|
|
313
|
+
return ignoreTimingsReturn;
|
|
263
314
|
const offset = section.startTime +
|
|
264
315
|
getFtbDuration(section, lessonInfo) -
|
|
265
316
|
firstTimedVerse.timings[0];
|
package/dist/functions/sets.js
CHANGED
|
@@ -168,6 +168,7 @@ function getLessonInfo({ lessonId, languageInfo, setInfo, t, useSpokenQuestions,
|
|
|
168
168
|
fileName: bibleStatuses_1.bibleStatuses[bibleId]?.customPassages?.[passageId]
|
|
169
169
|
? passageId + '.mp3'
|
|
170
170
|
: passageInfo.chapterAudioFileName,
|
|
171
|
+
header: (0, scripturePassages_1.getPassagesString)([{ bibleId, passageId }]),
|
|
171
172
|
});
|
|
172
173
|
lastBook = passageInfo.book;
|
|
173
174
|
});
|
|
@@ -201,6 +202,7 @@ function getLessonInfo({ lessonId, languageInfo, setInfo, t, useSpokenQuestions,
|
|
|
201
202
|
ftbFileName: ftbRequired
|
|
202
203
|
? `${languageInfo.contentLanguages.ftbs}.${passageInfo.book}.mp3`
|
|
203
204
|
: undefined,
|
|
205
|
+
header: (0, scripturePassages_1.getPassagesString)([{ bibleId: modifier.bibleId, passageId }]),
|
|
204
206
|
});
|
|
205
207
|
lastBook = passageInfo.book;
|
|
206
208
|
concatStoryIndex++;
|
|
@@ -208,7 +210,7 @@ function getLessonInfo({ lessonId, languageInfo, setInfo, t, useSpokenQuestions,
|
|
|
208
210
|
});
|
|
209
211
|
applicationQuestions.forEach((questionId, index) => {
|
|
210
212
|
const fileName = questionId.includes('video')
|
|
211
|
-
? `${languageInfo.contentLanguages.trainingVideos}.${lessonId}.
|
|
213
|
+
? `${languageInfo.contentLanguages.trainingVideos}.${lessonId}.mp4`
|
|
212
214
|
: `${languageInfo.contentLanguages.questionAudio}.${questionId}.mp3`;
|
|
213
215
|
sections.push({
|
|
214
216
|
id: questionId,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import z from 'zod';
|
|
2
2
|
import { BibleAudio } from '../data/bibleAudios/bibleAudios.zod';
|
|
3
3
|
import { BibleText } from '../data/bibleTexts/bibleTexts.zod';
|
|
4
|
+
import type { CurriculumOnboarding } from '../data/curriculumOnboarding/curriculumOnboarding.zod';
|
|
4
5
|
import type { CurriculumQuestions } from '../data/curriculumQuestions/curriculumQuestions.zod';
|
|
5
6
|
import { type Language } from '../data/languages/languages.zod';
|
|
6
7
|
import { LessonPauses } from '../data/lessonPauses/lessonPauses.zod';
|
|
@@ -16,6 +17,7 @@ export interface BibleInfo extends Omit<BibleText, 'language' | 'copyright'>, Om
|
|
|
16
17
|
availableTextChapters: string[];
|
|
17
18
|
availableTimingsChapters: string[];
|
|
18
19
|
availableAudioChapters: string[];
|
|
20
|
+
availableChapters: string[];
|
|
19
21
|
fullCopyright: string;
|
|
20
22
|
bookNames: Record<string, string>;
|
|
21
23
|
script: Scripts[number];
|
|
@@ -27,6 +29,7 @@ declare const RequiredBridgeLanguages: z.ZodObject<{
|
|
|
27
29
|
titles: z.ZodNonOptional<z.ZodOptional<z.ZodString>>;
|
|
28
30
|
questionText: z.ZodNonOptional<z.ZodOptional<z.ZodString>>;
|
|
29
31
|
questionAudio: z.ZodNonOptional<z.ZodOptional<z.ZodString>>;
|
|
32
|
+
onboardingPassages: z.ZodNonOptional<z.ZodOptional<z.ZodString>>;
|
|
30
33
|
}, z.core.$strip>;
|
|
31
34
|
type RequiredBridgeLanguages = z.infer<typeof RequiredBridgeLanguages>;
|
|
32
35
|
export interface LanguageInfo extends Omit<Language, 'bible' | 'bibleFallbacks' | 'script' | 'bridgeLanguages'> {
|
|
@@ -57,6 +60,12 @@ export interface LanguageInfo extends Omit<Language, 'bible' | 'bibleFallbacks'
|
|
|
57
60
|
*/
|
|
58
61
|
script: Scripts[number];
|
|
59
62
|
contentLanguages: RequiredBridgeLanguages;
|
|
63
|
+
/**
|
|
64
|
+
* The passage ids to use for the onboarding DBS, keyed by the user's "What
|
|
65
|
+
* brings you to Waha?" answer. Sourced from this language's onboarding
|
|
66
|
+
* curriculum (some languages use different psalm numberings).
|
|
67
|
+
*/
|
|
68
|
+
onboardingPassageIds: CurriculumOnboarding[number]['passages'];
|
|
60
69
|
}
|
|
61
70
|
export interface MeetTranslations {
|
|
62
71
|
sets: TranslationsSet[string];
|
|
@@ -2,7 +2,6 @@ import z from 'zod';
|
|
|
2
2
|
export declare const ScripturePassageSchema: z.ZodObject<{
|
|
3
3
|
passageId: z.ZodString;
|
|
4
4
|
bibleId: z.ZodString;
|
|
5
|
-
header: z.ZodString;
|
|
6
5
|
verses: z.ZodArray<z.ZodObject<{
|
|
7
6
|
text: z.ZodString;
|
|
8
7
|
timings: z.ZodOptional<z.ZodUnion<readonly [z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, z.ZodNull]>>;
|
|
@@ -9,6 +9,5 @@ const bibleChapters_1 = require("./bibleChapters");
|
|
|
9
9
|
exports.ScripturePassageSchema = zod_1.default.object({
|
|
10
10
|
passageId: zod_1.default.string(),
|
|
11
11
|
bibleId: zod_1.default.string(),
|
|
12
|
-
header: zod_1.default.string(),
|
|
13
12
|
verses: zod_1.default.array(bibleChapters_1.BibleVerse),
|
|
14
13
|
});
|
package/dist/types/sets.d.ts
CHANGED
|
@@ -50,6 +50,13 @@ export interface Section {
|
|
|
50
50
|
export interface EnrichedSection extends Section {
|
|
51
51
|
startTime: number;
|
|
52
52
|
length: number;
|
|
53
|
+
/**
|
|
54
|
+
* True when this section's `startTime` can't be trusted — currently set on
|
|
55
|
+
* story sections that follow another story whose length couldn't be
|
|
56
|
+
* determined (e.g. scripture still loading). Consumers should hide play
|
|
57
|
+
* buttons and skip these sections when snapping/seeking.
|
|
58
|
+
*/
|
|
59
|
+
ignoreTimings?: boolean;
|
|
53
60
|
}
|
|
54
61
|
export interface DbsInfo extends BaseInfo, SetInfo, Lesson {
|
|
55
62
|
type: 'dbs';
|