import com.russhwolf.settings.Settings import com.russhwolf.settings.StorageSettings import com.russhwolf.settings.set import com.ustadmobile.BuildConfigJs import com.ustadmobile.core.account.* import com.ustadmobile.core.db.UmAppDataLayer import com.ustadmobile.core.db.UmAppDatabase import com.ustadmobile.core.domain.filterusername.FilterUsernameUseCase import com.ustadmobile.core.domain.getversion.GetVersionUseCase import com.ustadmobile.core.domain.invite.ClazzInviteRedeemUseCase import com.ustadmobile.core.domain.learningspace.GoToLearningSpaceUseCase import com.ustadmobile.core.domain.learningspace.GoToLearningSpaceUseCaseJs import com.ustadmobile.core.domain.localaccount.GetLocalAccountsSupportedUseCase import com.ustadmobile.core.domain.person.bulkadd.BulkAddPersonsFromLocalUriUseCase import com.ustadmobile.core.domain.person.bulkadd.BulkAddPersonsFromLocalUriUseCaseJs import com.ustadmobile.core.domain.showpoweredby.GetShowPoweredByUseCase import com.ustadmobile.core.domain.socialwarning.DismissSocialWarningUseCase import com.ustadmobile.core.domain.socialwarning.ShowSocialWarningUseCase import com.ustadmobile.core.domain.validateusername.ValidateUsernameUseCase import com.ustadmobile.core.impl.* import com.ustadmobile.core.impl.config.SystemUrlConfig import com.ustadmobile.core.impl.config.UstadBuildConfig import com.ustadmobile.core.impl.config.BuildConfigMap import com.ustadmobile.core.impl.config.GenderConfig import com.ustadmobile.core.impl.config.SupportedLanguagesConfig import com.ustadmobile.core.impl.config.SupportedLanguagesConfig.Companion.PREFKEY_ACTIONED_PRESET import com.ustadmobile.core.impl.config.SupportedLanguagesConfig.Companion.PREFKEY_LOCALE import com.ustadmobile.core.impl.di.DomainDiModuleJs import com.ustadmobile.core.impl.di.commonDomainDiModule import com.ustadmobile.core.util.DiTag import com.ustadmobile.door.RepositoryConfig import com.ustadmobile.door.entities.NodeIdAndAuth import com.ustadmobile.door.ext.DoorTag import com.ustadmobile.door.ext.asRepository import com.ustadmobile.lib.db.entities.UmAccount import com.ustadmobile.xmlpullparserkmp.XmlPullParserFactory import com.ustadmobile.xmlpullparserkmp.XmlSerializer import io.ktor.client.* import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.serialization.json.Json import org.kodein.di.* import com.ustadmobile.core.impl.locale.StringProviderJs import com.ustadmobile.core.util.ext.toNullIfBlank import com.ustadmobile.domain.getversion.GetVersionUseCaseJs import com.ustadmobile.centralappconfigdb.datasource.CentralAppConfigDbDataSource import com.ustadmobile.centralappconfigdb.datasource.network.CentralAppConfigDbDataSourceHttp import com.ustadmobile.core.domain.invite.EnrollToCourseFromInviteCodeUseCase import com.ustadmobile.core.impl.di.commonClientDomainDiModule import com.ustadmobile.util.resolveEndpoint import dev.icerock.moko.resources.provider.JsStringProvider import nl.adaptivity.xmlutil.ExperimentalXmlUtilApi import nl.adaptivity.xmlutil.serialization.XML import nl.adaptivity.xmlutil.serialization.XmlConfig import web.location.location import web.navigator.navigator import web.url.URLSearchParams /** * KodeIn DI builder for JS/Browser. */ @OptIn(ExperimentalXmlUtilApi::class) internal fun ustadJsDi( dbBuilt: UmAppDatabase, dbNodeIdAndAuth: NodeIdAndAuth, json: Json, httpClient: HttpClient, stringsProvider: JsStringProvider, ) = DI { import(commonDomainDiModule(LearningSpaceScope.Default)) import(commonClientDomainDiModule(LearningSpaceScope.Default)) import(DomainDiModuleJs(LearningSpaceScope.Default)) val learningSpaceUrl = resolveEndpoint(location.href, URLSearchParams(location.search)) console.log("Learning Space URL = $learningSpaceUrl (location.href = ${location.href}") val isLearningSpace = js("_ustadLearningSpaceExists") as Boolean bind() with singleton { BuildConfigMap( buildMap { put(UstadBuildConfig.KEY_SYSTEM_URL, BuildConfigJs.SYSTEM_URL) put(UstadBuildConfig.KEY_PASSKEY_RP_ID, BuildConfigJs.PASSKEY_RP_ID) put(UstadBuildConfig.KEY_PRESET_LEARNING_SPACE_URL, BuildConfigJs.PRESET_LEARNING_SPACE_URL) put(UstadBuildConfig.KEY_NEW_PERSONAL_ACCOUNT_LEARNING_SPACE_URL, BuildConfigJs.NEW_PERSONAL_ACCOUNT_LEARNING_SPACE_URL) } ) } bind() with singleton { ShowSocialWarningUseCase( settings = instance() ) } bind() with singleton { DismissSocialWarningUseCase( settings = instance() ) } bind() with singleton { GenderConfig( genderConfigStr = BuildConfigJs.APP_UI_GOPTS.toNullIfBlank() ?: GenderConfig.DEFAULT_GENDER_OPTIONS ) } bind() with singleton { FilterUsernameUseCase() } bind() with singleton { ValidateUsernameUseCase() } bind() with singleton { StorageSettings().also { /* * Check if there is a preset default language, and apply if not already actioned */ val presetLang = BuildConfigJs.APP_PRESET_LOCALE if(!presetLang.isEmpty() && it.getStringOrNull(PREFKEY_ACTIONED_PRESET) != "true") { it[PREFKEY_LOCALE] = presetLang it[PREFKEY_ACTIONED_PRESET] = "true" } } } bind() with singleton { stringsProvider } bind() with singleton { val jsStringProvider: JsStringProvider = instance() val localeConfig: SupportedLanguagesConfig = instance() StringProviderJs(localeConfig.displayedLocale, jsStringProvider) } bind() with singleton { SupportedLanguagesConfig( availableLanguagesConfig = BuildConfigJs.APP_UI_LANGUAGES.toNullIfBlank() ?: SupportedLanguagesConfig.DEFAULT_SUPPORTED_LANGUAGES, systemLocales = navigator.languages.toList(), settings = instance(), ) } bind() with singleton { SystemUrlConfig.fromUstadBuildConfig(instance()).copy( presetLearningSpaceUrl = if (isLearningSpace) learningSpaceUrl else null ) } bind() with singleton { val jsStringProvider: JsStringProvider = instance() UstadMobileSystemImpl( settings = instance(), langConfig = instance(), jsStringProvider = jsStringProvider, ) } bind() with singleton { UstadAccountManager(settings = instance(), di = di) } bind() with scoped(LearningSpaceScope.Default).singleton { dbNodeIdAndAuth } bind() with singleton { CentralAppConfigDbDataSourceHttp( url = learningSpaceUrl + "api/${CentralAppConfigDbDataSource.PATH}/", httpClient = instance(), ) } bind(tag = DoorTag.TAG_DB) with scoped(LearningSpaceScope.Default).singleton { dbBuilt } bind() with scoped(LearningSpaceScope.Default).singleton { val nodeIdAndAuth: NodeIdAndAuth = instance() val db = instance(tag = DoorTag.TAG_DB) val repositoryConfig = RepositoryConfig.repositoryConfig( this,context.url+"UmAppDatabase/", nodeIdAndAuth.auth, nodeIdAndAuth.nodeId, httpClient = instance(), json = instance() ){ } UmAppDataLayer( localDb = db, repository = db.asRepository(repositoryConfig) ) } constant(UstadMobileSystemCommon.TAG_DOWNLOAD_ENABLED) with false bind(tag = DiTag.XPP_FACTORY_NSAWARE) with singleton { XmlPullParserFactory.newInstance().also { it.setNamespaceAware(true) } } bind(tag = DiTag.XPP_FACTORY_NSUNAWARE) with singleton { XmlPullParserFactory.newInstance() } bind() with provider { instance().newSerializer() } bind(tag = UstadMobileSystemCommon.TAG_MAIN_COROUTINE_CONTEXT) with singleton { Dispatchers.Main } bind() with singleton { httpClient } bind() with singleton { GetLocalAccountsSupportedUseCase(false) } registerContextTranslator { account: UmAccount -> LearningSpace(account.endpointUrl) } bind() with scoped(LearningSpaceScope.Default).singleton { AuthManager(context, di) } bind() with singleton { val numIterations = UstadMobileConstants.PBKDF2_ITERATIONS val keyLength = UstadMobileConstants.PBKDF2_KEYLENGTH Pbkdf2Params(numIterations, keyLength) } bind() with singleton { json } bind() with singleton { XML { defaultPolicy { unknownChildHandler = XmlConfig.IGNORING_UNKNOWN_CHILD_HANDLER } } } bind() with singleton { GetVersionUseCaseJs() } bind() with singleton { GoToLearningSpaceUseCaseJs(di) } bind() with singleton { GetShowPoweredByUseCase(BuildConfigJs.APP_UI_SHOW_POWERED_BY.toBoolean()) } bind() with scoped(LearningSpaceScope.Default).provider { ClazzInviteRedeemUseCase( enrolIntoCourseUseCase = instance(), db = instance(tag = DoorTag.TAG_DB), repo = instance().repositoryOrLocalDb, systemImpl = instance(), ) } bind() with scoped(LearningSpaceScope.Default).provider { EnrollToCourseFromInviteCodeUseCase( clazzInviteRedeemUseCase = instance() ) } bind() with scoped(LearningSpaceScope.Default).provider { BulkAddPersonsFromLocalUriUseCaseJs( httpClient = instance(), learningSpace = context, json = instance(), repo = instance().repositoryOrLocalDb, ) } }