import org.json.JSONObject import java.util.concurrent.atomic.AtomicInteger plugins { id 'org.jetbrains.kotlin.multiplatform' id 'org.jetbrains.kotlin.plugin.atomicfu' id 'org.jetbrains.kotlin.plugin.serialization' id 'com.android.library' id 'maven-publish' } android { compileSdkVersion rootProject.ext.version_android_compile_sdk buildTypes { release { consumerProguardFiles 'proguard-rules.pro' } } defaultConfig { minSdkVersion 21 targetSdkVersion rootProject.ext.version_android_target_sdk } packagingOptions { resources { // .kotlin_metadata files come from multiplatform modules, but are not needed unless we // use kotlin reflection, which we don't. excludes += ['META-INF/INDEX.LIST', '**/*.kotlin_metadata', 'META-INF/*.kotlin_module', 'licenses/**.TXT'] } } compileOptions { sourceCompatibility = '1.8' targetCompatibility = '1.8' //This will apparently prevent Android Studio from recognizing the project //coreLibraryDesugaringEnabled true } namespace 'com.ustadmobile.core' tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) { kotlinOptions { jvmTarget = "1.8" } } } sourceCompatibility = '1.8' targetCompatibility = '1.8' group rootProject.group version rootProject.version def reactLocaleOutPath = "${rootDir.absolutePath}/app-react/src/main/resources/" // workaround for https://youtrack.jetbrains.com/issue/KT-27170 configurations { compileClasspath } kotlin { jvm { compilations.main.kotlinOptions { // Setup the Kotlin compiler options for the 'main' compilation: jvmTarget = "$version_kotlin_jvmTarget" } compilations.test.kotlinOptions { // Setup the Kotlin compiler options for the 'main' compilation: jvmTarget = "$version_kotlin_jvmTarget" } } android() js(LEGACY) { browser { dceTask { keep("kotlin.defineModule") //To avoid e.defineModule is not a function error } testTask { useKarma { useChromeHeadless() //change to useChrome to run the actual browser webpackConfig.cssSupport.enabled = true } } } } sourceSets { commonMain { kotlin.srcDirs += "build/generated/source/umlocale/" kotlin.srcDirs += "build/generated/source/umlocale-namemap" dependencies { implementation kotlin('stdlib-common') implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$version_kotlinx_serialization" implementation "io.ktor:ktor-client-core:$version_ktor" implementation "io.ktor:ktor-client-json:$version_ktor" implementation "io.ktor:ktor-client-content-negotiation:$version_ktor" implementation "io.ktor:ktor-io:$version_ktor" implementation "com.soywiz.korlibs.klock:klock:$version_klock" implementation "io.github.aakira:napier:$version_napier" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version_coroutines" implementation "com.github.UstadMobile.door:door-runtime:$version_door" implementation "org.kodein.di:kodein-di:$version_kodein_di" implementation project(':lib-database') implementation "com.github.UstadMobile.door:door-runtime:$version_door" implementation project(":lib-util") implementation "com.ustadmobile.xmlpullparserkmp:xmlpullparserkmp:$version_xmlpullparserkmp" implementation "org.jetbrains.kotlinx:atomicfu:$version_atomicfu" } } commonJvmMain { dependsOn commonMain dependencies { implementation kotlin('stdlib-common') implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version_coroutines" implementation "io.ktor:ktor-client-okhttp:$version_ktor" implementation "io.ktor:ktor-client-cio:$version_ktor" implementation "io.ktor:ktor-serialization-gson:$version_ktor" implementation "org.kodein.di:kodein-di:$version_kodein_di" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version_coroutines" implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$version_kotlinx_serialization" implementation "com.squareup.okhttp3:okhttp:$version_okhttp" compileOnly "net.sf.kxml:kxml2:$version_kxml" } } commonTest { dependencies { implementation kotlin('test-common') implementation kotlin('test-annotations-common') } } jvmMain { dependsOn commonJvmMain resources.srcDirs += ["locale/main", "src/main/assets"] dependencies { implementation "org.apache.pdfbox:pdfbox:$version_pdfbox_apache" implementation "org.jsoup:jsoup:$version_jsoup" implementation "com.google.code.gson:gson:$version_gson" implementation "com.squareup.okhttp3:okhttp:$version_okhttp" implementation "org.quartz-scheduler:quartz:$version_quartz_scheduler" } } jvmTest { dependencies { implementation "org.jetbrains.kotlin:kotlin-test:$version_kotlin" implementation "org.jetbrains.kotlin:kotlin-test-junit:$version_kotlin" implementation "org.mockito.kotlin:mockito-kotlin:$version_kotlin_mockito" implementation "junit:junit:$version_junit" implementation project(":sharedse") implementation project(":lib-test-common") implementation project(":app-ktor-server") implementation "com.github.h-thurow:simple-jndi:$version_simple_jndi" implementation "org.apache.commons:commons-pool2:$version_apache_commons_pool2" implementation "org.xerial:sqlite-jdbc:$version_sqlite_jdbc" implementation "org.apache.commons:commons-dbcp2:$version_apache_commons_dbcp2" implementation "org.nanohttpd:nanohttpd:$version_nanohttpd" implementation "org.nanohttpd:nanohttpd-nanolets:$version_nanohttpd" implementation "com.squareup.okhttp3:mockwebserver:$version_mockwebserver" implementation "io.ktor:ktor-server-netty:$version_ktor" implementation "io.ktor:ktor-serialization-gson:$version_ktor" implementation "io.ktor:ktor-serialization-gson:$version_ktor" implementation "org.kodein.di:kodein-di-framework-ktor-server-jvm:$version_kodein_di" implementation "net.bytebuddy:byte-buddy:1.12.18" } } androidMain { dependsOn commonJvmMain dependencies { implementation "com.dmitryborodin:pdfview-android:$version_pdfview_android" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version_kotlin" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version_coroutines" implementation "androidx.lifecycle:lifecycle-livedata-ktx:$version_androidx_lifecycle" implementation "androidx.room:room-runtime:$version_android_room" implementation "com.google.code.gson:gson:$version_gson" implementation "androidx.appcompat:appcompat:$version_androidx_appcompat" implementation "androidx.legacy:legacy-support-v4:$version_androidx_legacy" //Seems to fix things when we put a specific dependency here implementation "androidx.coordinatorlayout:coordinatorlayout:$version_androidx_coordinatorlayout" implementation "androidx.recyclerview:recyclerview:$version_androidx_recyclerview" implementation "androidx.room:room-runtime:$version_android_room" implementation "androidx.paging:paging-runtime:$version_androidx_paging" implementation "androidx.work:work-runtime:$version_android_workmanager" implementation "androidx.work:work-runtime-ktx:$version_android_workmanager" implementation "org.jsoup:jsoup:$version_jsoup" //Image loading library implementation "com.squareup.picasso:picasso:$version_android_picasso" implementation "io.ktor:ktor-client-android:$version_ktor" implementation "io.ktor:ktor-serialization-gson:$version_ktor" implementation "com.linkedin.android.litr:litr:$version_android_litr" //dependency injection implementation "org.kodein.di:kodein-di-framework-android-x:$version_kodein_di" implementation "com.squareup.okhttp3:okhttp:$version_okhttp" implementation "androidx.navigation:navigation-fragment-ktx:$version_android_navigation" implementation "androidx.navigation:navigation-ui-ktx:$version_android_navigation" implementation "com.google.android.material:material:$version_android_material" } } jsMain { dependencies { implementation "io.ktor:ktor-client-js:$version_ktor" implementation "io.ktor:ktor-client-json-js:$version_ktor" implementation "io.ktor:ktor-client-serialization-js:$version_ktor" implementation "org.jetbrains.kotlin-wrappers:kotlin-extensions:$version_kotlin_extensions" implementation npm("asmcrypto.js","$version_npm_asmcrypto") implementation npm("buffer","$version_npm_buffer") } } jsTest { dependencies { implementation kotlin('test-js') implementation npm("moment","$version_npm_moment") implementation npm("moment-timezone","$version_npm_moment_timezone") } } } } /* * Generate a class with constant integer flags for each string message ID. See localization docs * for further information. */ task prepareLocale { inputs.files(fileTree(dir: project.file("locale")).matching { include '**/*.xml' }) outputs.file("build/generated/source/umlocale/com/ustadmobile/core/generated/locale/MessageID.kt") doFirst { File messageIdFile = project.file("build/generated/source/umlocale/com/ustadmobile/core/generated/locale/MessageID.kt") if(!messageIdFile.parentFile.exists()) { messageIdFile.parentFile.mkdirs() } messageIdFile.text = '' messageIdFile << 'package com.ustadmobile.core.generated.locale\n\n' messageIdFile << '/** DO NOT EDIT. GENERATED CODE */\n' messageIdFile << 'object MessageID{\n\n' String messageIdMap = """package com.ustadmobile.core.generated.locale\n\n object MessageIdMap { private val strMap = mapOf( """ Map messageIds = new HashMap<>() AtomicInteger messageIdGenerator = new AtomicInteger(2000) rootProject.fileTree(dir: "core/locale/main/values", include: "*.xml").each() { File file -> def xmlDoc = new XmlSlurper().parseText(file.getText("UTF-8")) xmlDoc.string.each() { str -> String msgName = str.@name if (!messageIds.containsKey(msgName)) { messageIds.put(msgName, new Integer(messageIdGenerator.getAndIncrement())) } } } Iterator nameIterator = messageIds.keySet().iterator() boolean first = true while (nameIterator.hasNext()) { String strName = nameIterator.next() Integer value = messageIds.get(strName) messageIdFile << ' const val ' + strName + ' = ' + String.valueOf(value) + '\n\n' if(!first) { messageIdMap += ",\n" } messageIdMap += String.valueOf(value) + ' to "' + strName + '"' first = false } messageIdFile << '}' messageIdMap += """) operator fun get(messageId: Int) = strMap[messageId] val idMap: Map = strMap.toMap() }""" File messageIdMapFile = project.file("build/generated/source/umlocale-namemap/com/ustadmobile/core/generated/locale/MessageIdMap.kt") if(!messageIdMapFile.parentFile.exists()) { messageIdMapFile.parentFile.mkdirs() } messageIdMapFile.text = messageIdMap } } task copyStringValuesToWebAssets { File outDir = project.file("${reactLocaleOutPath}/locales/") if(!outDir.exists()){ outDir.mkdirs() } rootProject.fileTree(dir: "core/locale/main").each() { File file -> def localeCode = "en" def pathString = file.absolutePath.substring(file.absolutePath.lastIndexOf("values")) if(pathString.split("-").size() > 1){ localeCode = file.getParent().substring(file.getParent().lastIndexOf("-") + 1) } FileWriter writer = new FileWriter(project.file("${outDir.absolutePath}/${localeCode}.xml").absolutePath) writer.write(file.getText()) writer.flush() } } task prepareAppConfigs{ try { File outFile = project.file("${reactLocaleOutPath}appconfig.json") File configFile = project.file("${rootDir.absolutePath}/core/src/main/assets/" + "com/ustadmobile/core/appconfig.properties") Scanner scanner = new Scanner(configFile) def configContent = new JSONObject() while(scanner.hasNextLine()){ String line = scanner.nextLine() if(!line.startsWith("#") && !line.isEmpty()){ def keyValue = line.replace(" ","").split("=") if(keyValue.length > 1){ configContent.put(keyValue[0],keyValue[1]) } } } FileWriter jsonFile = new FileWriter(outFile.absolutePath) jsonFile.write(configContent.toString(4)) jsonFile.flush() }catch(FileNotFoundException e){ e.printStackTrace() } } tasks.whenTaskAdded { task -> if (task.name == "compileTestKotlinJvm") { task.dependsOn(copyTestResources) } if(task.name.startsWith("compile") || task.name.startsWith("assemble") || task.name.endsWith("Jar") || task.name.startsWith("build")) { task.dependsOn(prepareLocale) } } gradle.projectsEvaluated { preBuild.dependsOn(prepareLocale, copyStringValuesToWebAssets, prepareAppConfigs) } publishing { publications { maven(MavenPublication) { groupId rootProject.group artifactId project.name version rootProject.version } } repositories { maven { url rootProject.ext.buildConfigProperties['repo.dir'] } } }