From 7fba35898c18c9cc6661c24a8b79c5c759df52c7 Mon Sep 17 00:00:00 2001 From: Andrew Sidorchuk Date: Sat, 29 Nov 2025 13:22:12 -0500 Subject: [PATCH 1/3] refactor: rename type to BibleReferenceBase --- src/api/bible.ts | 6 +++--- src/native.ts | 4 ++-- src/types.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/api/bible.ts b/src/api/bible.ts index 4decca4..42e4548 100644 --- a/src/api/bible.ts +++ b/src/api/bible.ts @@ -1,5 +1,5 @@ import { Module } from "../native"; -import { BibleReference, BibleVersion } from "../types"; +import { BibleReferenceBase, BibleVersion } from "../types"; export const BibleAPI = { /** @@ -26,10 +26,10 @@ export const BibleAPI = { /** * Retrieves the content of a single Bible chapter from the server as an HTML string. * - * @param bibleReference - A {@link BibleReference} object specifying the reference to retrieve. + * @param bibleReference - A {@link BibleReferenceBase} object specifying the reference to retrieve. * @returns The chapter content as an HTML string. */ - getChapter(bibleReference: BibleReference): Promise { + getChapter(bibleReference: BibleReferenceBase): Promise { return Module.chapter(bibleReference); }, }; diff --git a/src/native.ts b/src/native.ts index 7db4de1..eab1346 100644 --- a/src/native.ts +++ b/src/native.ts @@ -1,7 +1,7 @@ import { NativeModule, requireNativeModule } from "expo"; import { - BibleReference, + BibleReferenceBase, BibleVersion, HighlightResponse, LanguageOverview, @@ -48,7 +48,7 @@ declare class RNYouVersionPlatformModule extends NativeModule { version(versionId: number): Promise; - chapter(bibleReference: BibleReference): Promise; + chapter(bibleReference: BibleReferenceBase): Promise; getAccessToken(): string | null; } diff --git a/src/types.ts b/src/types.ts index 61dab51..acabcd3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -90,7 +90,7 @@ export interface BibleTextOptions { export type BibleTextFootnoteMode = "none" | "inline" | "marker"; -interface BibleReferenceBase { +export interface BibleReferenceBase { /** The ID of the Bible version */ versionId: number; From 7651ce9d75ee07b762d32e6e5c4429e7bb583b23 Mon Sep 17 00:00:00 2001 From: Andrew Sidorchuk Date: Sat, 29 Nov 2025 13:22:45 -0500 Subject: [PATCH 2/3] docs: update to match changes in docs site --- src/api/bible.ts | 2 +- src/types.ts | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/api/bible.ts b/src/api/bible.ts index 42e4548..50e08ae 100644 --- a/src/api/bible.ts +++ b/src/api/bible.ts @@ -3,7 +3,7 @@ import { BibleReferenceBase, BibleVersion } from "../types"; export const BibleAPI = { /** - * Retrieves a list of Bible versions available for a specified language code (like "en"). + * Retrieves a list of Bible versions available for a specified language tag (like "eng"). * * @param languageTag - An optional language code per BCP 47 for filtering available Bible versions. If `nil` * the function returns versions for all languages. diff --git a/src/types.ts b/src/types.ts index acabcd3..67444fc 100644 --- a/src/types.ts +++ b/src/types.ts @@ -352,11 +352,25 @@ export interface BibleBook { * @example "Genesis" */ title?: string; - titleLong?: string; + + /** + * Indicates if this is Old Testament, New Testament, or Deuterocanonical + * + * @example "ot" + */ + canon?: "nt" | "ot" | "dc"; + chapters?: BibleChapter[]; } export interface BibleChapter { + /** + * Chapter identifier based off the USFM reference + * + * @example 1 + */ + id?: string; + /** * Book identifier * From 48b1f10ca5457941eb5f3d23ad1156dcd7b9c1b9 Mon Sep 17 00:00:00 2001 From: Andrew Sidorchuk Date: Sat, 29 Nov 2025 13:25:12 -0500 Subject: [PATCH 3/3] feat: implement api endpoints for Kotlin side --- .../RNYouVersionPlatformModule.kt | 62 +++++++ .../reactnativesdk/api/YVPBibleApi.kt | 32 ++++ .../reactnativesdk/api/YVPHighlightsApi.kt | 44 +++++ .../reactnativesdk/api/YVPLanguagesApi.kt | 11 ++ .../reactnativesdk/api/YVPRecords.kt | 168 ++++++++++++++++++ 5 files changed, 317 insertions(+) create mode 100644 android/src/main/java/com/youversion/reactnativesdk/api/YVPBibleApi.kt create mode 100644 android/src/main/java/com/youversion/reactnativesdk/api/YVPHighlightsApi.kt create mode 100644 android/src/main/java/com/youversion/reactnativesdk/api/YVPLanguagesApi.kt diff --git a/android/src/main/java/com/youversion/reactnativesdk/RNYouVersionPlatformModule.kt b/android/src/main/java/com/youversion/reactnativesdk/RNYouVersionPlatformModule.kt index 3e3ed02..93b91ff 100644 --- a/android/src/main/java/com/youversion/reactnativesdk/RNYouVersionPlatformModule.kt +++ b/android/src/main/java/com/youversion/reactnativesdk/RNYouVersionPlatformModule.kt @@ -1,6 +1,10 @@ package com.youversion.reactnativesdk import com.youversion.platform.core.YouVersionPlatformConfiguration +import com.youversion.reactnativesdk.api.BibleReferenceRecord +import com.youversion.reactnativesdk.api.YVPBibleApi +import com.youversion.reactnativesdk.api.YVPHighlightsApi +import com.youversion.reactnativesdk.api.YVPLanguagesApi import com.youversion.reactnativesdk.api.YVPVotdApi import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition @@ -33,5 +37,63 @@ class RNYouVersionPlatformModule : Module() { dayOfYear = dayOfYear ) } + + AsyncFunction("languages") Coroutine { country: String? -> + return@Coroutine YVPLanguagesApi.languages( + country = country + ) + } + + AsyncFunction("versions") Coroutine { languageTag: String? -> + return@Coroutine YVPBibleApi.versions( + languageTag = languageTag + ) + } + + AsyncFunction("version") Coroutine { versionId: Int -> + return@Coroutine YVPBibleApi.version( + versionId = versionId + ) + } + + AsyncFunction("chapter") Coroutine { bibleReference: BibleReferenceRecord -> + val context = appContext.reactContext + ?: throw IllegalStateException("ReactContext is not available yet") + + return@Coroutine YVPBibleApi.chapter( + bibleReference = bibleReference, + context = context + ) + } + + AsyncFunction("createHighlight") Coroutine { bibleId: Int, passageId: String, color: String -> + return@Coroutine YVPHighlightsApi.createHighlight( + bibleId = bibleId, + passageId = passageId, + color = color + ) + } + + AsyncFunction("getHighlights") Coroutine { bibleId: Int, passageId: String -> + return@Coroutine YVPHighlightsApi.getHighlights( + bibleId = bibleId, + passageId = passageId, + ) + } + + AsyncFunction("updateHighlight") Coroutine { bibleId: Int, passageId: String, color: String -> + return@Coroutine YVPHighlightsApi.updateHighlight( + bibleId = bibleId, + passageId = passageId, + color = color + ) + } + + AsyncFunction("deleteHighlight") Coroutine { bibleId: Int, passageId: String -> + return@Coroutine YVPHighlightsApi.deleteHighlight( + bibleId = bibleId, + passageId = passageId + ) + } } } diff --git a/android/src/main/java/com/youversion/reactnativesdk/api/YVPBibleApi.kt b/android/src/main/java/com/youversion/reactnativesdk/api/YVPBibleApi.kt new file mode 100644 index 0000000..8808a5f --- /dev/null +++ b/android/src/main/java/com/youversion/reactnativesdk/api/YVPBibleApi.kt @@ -0,0 +1,32 @@ +package com.youversion.reactnativesdk.api + +import android.content.Context +import com.youversion.platform.core.api.YouVersionApi +import com.youversion.platform.core.bibles.domain.BibleReference +import com.youversion.platform.core.bibles.domain.BibleVersionRepository + +object YVPBibleApi { + suspend fun versions(languageTag: String?): List { + val response = YouVersionApi.bible.versions(languageTag) + val records = response.map { BibleVersionRecord(it) } + return records + } + + suspend fun version(versionId: Int): BibleVersionRecord { + val response = YouVersionApi.bible.version(versionId) + val record = BibleVersionRecord(response) + return record + } + + suspend fun chapter(bibleReference: BibleReferenceRecord, context: Context): String { + val response = BibleVersionRepository(context).chapter( + reference = BibleReference( + versionId = bibleReference.versionId, + bookUSFM = bibleReference.bookUSFM, + chapter = bibleReference.chapter, + ) + ) + + return response + } +} \ No newline at end of file diff --git a/android/src/main/java/com/youversion/reactnativesdk/api/YVPHighlightsApi.kt b/android/src/main/java/com/youversion/reactnativesdk/api/YVPHighlightsApi.kt new file mode 100644 index 0000000..c139b60 --- /dev/null +++ b/android/src/main/java/com/youversion/reactnativesdk/api/YVPHighlightsApi.kt @@ -0,0 +1,44 @@ +package com.youversion.reactnativesdk.api + +import com.youversion.platform.core.api.YouVersionApi + +object YVPHighlightsApi { + suspend fun createHighlight(bibleId: Int, passageId: String, color: String): Boolean { + val response = YouVersionApi.highlights.createHighlight( + versionId = bibleId, + passageId = passageId, + color = color + ) + + return response + } + + suspend fun getHighlights(bibleId: Int, passageId: String): List { + val response = YouVersionApi.highlights.highlights( + versionId = bibleId, + passageId = passageId + ) + + val records = response.map { HighlightRecord(it) } + return records + } + + suspend fun updateHighlight(bibleId: Int, passageId: String, color: String): Boolean { + val response = YouVersionApi.highlights.updateHighlight( + versionId = bibleId, + passageId = passageId, + color = color + ) + + return response + } + + suspend fun deleteHighlight(bibleId: Int, passageId: String): Boolean { + val response = YouVersionApi.highlights.deleteHighlight( + versionId = bibleId, + passageId = passageId, + ) + + return response + } +} \ No newline at end of file diff --git a/android/src/main/java/com/youversion/reactnativesdk/api/YVPLanguagesApi.kt b/android/src/main/java/com/youversion/reactnativesdk/api/YVPLanguagesApi.kt new file mode 100644 index 0000000..106678f --- /dev/null +++ b/android/src/main/java/com/youversion/reactnativesdk/api/YVPLanguagesApi.kt @@ -0,0 +1,11 @@ +package com.youversion.reactnativesdk.api + +import com.youversion.platform.core.api.YouVersionApi + +object YVPLanguagesApi { + suspend fun languages(country: String?): List { + val response = YouVersionApi.language.languages(country) + val records = response.map { LanguageRecord(it) } + return records + } +} \ No newline at end of file diff --git a/android/src/main/java/com/youversion/reactnativesdk/api/YVPRecords.kt b/android/src/main/java/com/youversion/reactnativesdk/api/YVPRecords.kt index ea2a464..6518f29 100644 --- a/android/src/main/java/com/youversion/reactnativesdk/api/YVPRecords.kt +++ b/android/src/main/java/com/youversion/reactnativesdk/api/YVPRecords.kt @@ -1,5 +1,10 @@ package com.youversion.reactnativesdk.api +import com.youversion.platform.core.bibles.models.BibleBook +import com.youversion.platform.core.bibles.models.BibleChapter +import com.youversion.platform.core.bibles.models.BibleVersion +import com.youversion.platform.core.highlights.models.Highlight +import com.youversion.platform.core.languages.models.Language import com.youversion.platform.core.votd.models.YouVersionVerseOfTheDay import expo.modules.kotlin.records.Field import expo.modules.kotlin.records.Record @@ -15,3 +20,166 @@ data class YouVersionVerseOfTheDayRecord( day = votd.day ) } + +data class LanguageRecord( + @Field + val id: String, + @Field + val language: String, + @Field + val script: String?, + @Field + val scriptName: String?, + @Field + val aliases: List, + @Field + val displayNames: Map, + @Field + val scripts: List, + @Field + val variants: List, + @Field + val countries: List, + @Field + val textDirection: String, + @Field + val defaultBibleVersionId: Int? + +) : Record { + constructor(language: Language) : this( + id = language.id, + language = language.language, + script = language.script, + scriptName = language.scriptName, + aliases = language.aliases, + displayNames = language.displayNames, + scripts = language.scripts, + variants = language.variants, + countries = language.countries, + textDirection = language.textDirection, + defaultBibleVersionId = language.defaultBibleVersionId + ) +} + +data class BibleVersionRecord( + @Field + val id: Int, + @Field + val abbreviation: String?, + @Field + val copyrightLong: String?, + @Field + val copyrightShort: String?, + @Field + val languageTag: String?, + @Field + val localizedAbbreviation: String?, + @Field + val localizedTitle: String?, + @Field + val readerFooter: String?, + @Field + val readerFooterUrl: String?, + @Field + val title: String?, + @Field + val bookCodes: List?, + @Field + val books: List?, + @Field + val textDirection: String? +) : Record { + constructor(bibleVersion: BibleVersion) : this( + id = bibleVersion.id, + abbreviation = bibleVersion.abbreviation, + copyrightLong = bibleVersion.copyrightLong, + copyrightShort = bibleVersion.copyrightShort, + languageTag = bibleVersion.languageTag, + localizedAbbreviation = bibleVersion.localizedAbbreviation, + localizedTitle = bibleVersion.localizedTitle, + readerFooter = bibleVersion.readerFooter, + readerFooterUrl = bibleVersion.readerFooterUrl, + title = bibleVersion.title, + bookCodes = bibleVersion.bookCodes, + books = bibleVersion.books?.map { BibleBookRecord(it) }, + textDirection = bibleVersion.textDirection + ) +} + +data class BibleBookRecord( + @Field + val usfm: String?, + @Field + val title: String?, + @Field + val abbreviation: String?, + @Field + val canon: String?, + @Field + val chapters: List? +) : Record { + constructor(bibleBook: BibleBook) : this( + usfm = bibleBook.usfm, + title = bibleBook.title, + abbreviation = bibleBook.abbreviation, + canon = bibleBook.canon, + chapters = bibleBook.chapters?.map { BibleChapterRecord(it) } + ) +} + +data class BibleChapterRecord( + @Field + val id: String?, + @Field + val bookUSFM: String?, + @Field + val isCanonical: Boolean?, + @Field + val passageId: String?, + @Field + val title: String? +) : Record { + constructor(bibleChapter: BibleChapter) : this( + id = bibleChapter.id, + bookUSFM = bibleChapter.bookUSFM, + isCanonical = bibleChapter.isCanonical, + passageId = bibleChapter.passageId, + title = bibleChapter.title + ) +} + +data class BibleReferenceRecord( + @Field + val versionId: Int, + @Field + val bookUSFM: String, + @Field + val chapter: Int, +) : Record + +data class HighlightRecord( + @Field + val id: String?, + @Field + val bibleId: Int, + @Field + val passageId: String, + @Field + val color: String, + @Field + val userId: String?, + @Field + val createTime: String?, + @Field + val updateTime: String? +) : Record { + constructor(highlight: Highlight) : this( + id = highlight.id, + bibleId = highlight.versionId, + passageId = highlight.passageId, + color = highlight.color, + userId = highlight.userId, + createTime = highlight.createTime, + updateTime = highlight.updateTime + ) +} \ No newline at end of file