diff --git a/README.md b/README.md index b99a182b..5c8db2e0 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ 0. 100% Kotlin [![awesome-kotlin](https://kotlin.link/awesome-kotlin.svg)](https://kotlin.link) 1. Jetpack Compose -2. MVI/Repository Pattern (MVI framework: [Orbit](https://github.com/orbit-mvi/orbit-mvi)) +2. MVVM+MVI/Repository Pattern (MVI framework: [Orbit](https://github.com/orbit-mvi/orbit-mvi)) 3. Coroutines, Flow 4. Retrofit, OkHttp 5. Dagger2 - Hilt diff --git a/build.gradle.kts b/build.gradle.kts index 16627355..f0611a25 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,9 +17,9 @@ buildscript { } dependencies { - classpath("com.chaquo.python:gradle:${Versions.Essential.Python}") + classpath("com.chaquo.python:gradle:${Versions.Bot.Python}") classpath("com.android.tools.build:gradle:${Versions.Essential.Gradle}") - classpath("com.google.dagger:hilt-android-gradle-plugin:${Versions.Hilt.Master}") + classpath("com.google.dagger:hilt-android-gradle-plugin:${Versions.Jetpack.Hilt}") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.Essential.Kotlin}") classpath("com.google.android.gms:oss-licenses-plugin:${Versions.OssLicense.Classpath}") } @@ -39,8 +39,8 @@ allprojects { tasks.withType { kotlinOptions { freeCompilerArgs = freeCompilerArgs + listOf( - "-Xopt-in=kotlin.RequiresOptIn", - "-Xopt-in=kotlin.OptIn" + "-Xopt-in=kotlin.OptIn", + "-Xopt-in=kotlin.RequiresOptIn" ) } } diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 6169254d..05996ab1 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -11,8 +11,8 @@ import org.gradle.api.JavaVersion object Application { const val minSdk = 24 - const val targetSdk = 30 - const val compileSdk = 30 + const val targetSdk = 31 + const val compileSdk = 31 const val jvmTarget = "11" const val versionCode = 1 const val versionName = "please_die_fucking_covid" @@ -22,15 +22,17 @@ object Application { } object Versions { + const val Orbit = "4.2.0" + object Essential { - const val Python = "9.1.0" - const val Kotlin = "1.5.21" + const val Kotlin = "1.5.31" const val CoreKtx = "1.6.0" const val Coroutines = "1.5.1" - const val Gradle = "7.1.0-alpha05" + const val Gradle = "7.1.0-beta02" } object Bot { + const val Python = "9.1.0" const val Rhino = "1.7.13" const val J2V8 = "6.2.1@aar" } @@ -38,48 +40,39 @@ object Versions { object Ui { const val Browser = "1.3.0" const val Material = "1.4.0" - const val TimeLineView = "1.0.2" - const val LottieCompose = "4.1.0" - const val FancyBottomBar = "1.0.1" - const val LandscapistCoil = "1.3.6" - const val ConstraintLayout = "1.0.0-beta01" } object Util { - const val Pluto = "1.0.7" - const val Timber = "5.0.1" + const val Pluto = "1.1.1" + const val Erratum = "1.0.1" + const val Logeukes = "1.0.0" + const val Jackson = "2.13.0" const val LeakCanary = "2.7" const val KeyboardObserver = "1.0.1" - const val ViewColorGenerator = "v0.1" const val CheckDependencyUpdates = "1.5.0" } object Network { - const val Jsoup = "1.14.2" - const val OkHttp = "4.9.1" + const val Jsoup = "1.14.3" + const val OkHttp = "4.9.2" const val Retrofit = "2.9.0" } object Jetpack { const val Room = "2.3.0" - } - - object Jackson { - const val Master = "2.12.5" - } - - object Hilt { - const val Master = "2.38.1" + const val Hilt = "2.40" } object Compose { - const val Master = "1.0.2" - const val Activity = "1.3.1" - } - - object Lifecycle { - const val Master = "2.3.1" - const val Compose = "1.0.0-alpha07" + const val Lottie = "4.2.0" + const val Master = "1.0.5" + const val Activity = "1.4.0" + const val Lifecycle = "2.4.0" + const val TimeLineView = "1.0.2" + const val FancyBottomBar = "1.0.1" + const val LandscapistCoil = "1.4.1" + const val Navigation = "2.4.0-alpha09" + const val ConstraintLayout = "1.0.0-beta01" } object OssLicense { @@ -89,83 +82,76 @@ object Versions { } object Dependencies { - const val jsoup = "org.jsoup:jsoup:${Versions.Network.Jsoup}" - + const val Jsoup = "org.jsoup:jsoup:${Versions.Network.Jsoup}" + const val Orbit = "org.orbit-mvi:orbit-viewmodel:${Versions.Orbit}" const val browser = "androidx.browser:browser:${Versions.Ui.Browser}" const val LandscapistCoil = - "com.github.skydoves:landscapist-coil:${Versions.Ui.LandscapistCoil}" + "com.github.skydoves:landscapist-coil:${Versions.Compose.LandscapistCoil}" - const val hilt = "com.google.dagger:hilt-android:${Versions.Hilt.Master}" - const val hiltCompiler = "com.google.dagger:hilt-android-compiler:${Versions.Hilt.Master}" + const val Hilt = "com.google.dagger:hilt-android:${Versions.Jetpack.Hilt}" + const val HiltCompiler = "com.google.dagger:hilt-android-compiler:${Versions.Jetpack.Hilt}" - const val roomCompiler = "androidx.room:room-compiler:${Versions.Jetpack.Room}" + const val RoomCompiler = "androidx.room:room-compiler:${Versions.Jetpack.Room}" - const val livedata = - "androidx.lifecycle:lifecycle-livedata-core-ktx:${Versions.Lifecycle.Master}" - - const val jacksonModule = - "com.fasterxml.jackson.module:jackson-module-kotlin:${Versions.Jackson.Master}" + val Essential = listOf( + "androidx.core:core-ktx:${Versions.Essential.CoreKtx}", + "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.Essential.Coroutines}" + ) - val bot = listOf( + val Bot = listOf( "org.mozilla:rhino:${Versions.Bot.Rhino}", "com.eclipsesource.j2v8:j2v8:${Versions.Bot.J2V8}" ) - val debug = listOf( - "com.mocklets:pluto:${Versions.Util.Pluto}", - "com.squareup.leakcanary:leakcanary-android:${Versions.Util.LeakCanary}" + val Ui = listOf( + "com.google.android.material:material:${Versions.Ui.Material}", + "com.google.android.gms:play-services-oss-licenses:${Versions.OssLicense.Master}" ) - val release = listOf("com.mocklets:pluto-no-op:${Versions.Util.Pluto}") - - val jackson = listOf( - "com.fasterxml.jackson.core:jackson-core:${Versions.Jackson.Master}", - "com.fasterxml.jackson.core:jackson-databind:${Versions.Jackson.Master}", - "com.fasterxml.jackson.core:jackson-annotations:${Versions.Jackson.Master}" + val Jackson = listOf( + "com.fasterxml.jackson.core:jackson-core:${Versions.Util.Jackson}", + "com.fasterxml.jackson.core:jackson-databind:${Versions.Util.Jackson}", + "com.fasterxml.jackson.core:jackson-annotations:${Versions.Util.Jackson}", + "com.fasterxml.jackson.module:jackson-module-kotlin:${Versions.Util.Jackson}" ) - val retrofit = listOf( + val Retrofit = listOf( "com.squareup.okhttp3:okhttp:${Versions.Network.OkHttp}", "com.squareup.retrofit2:retrofit:${Versions.Network.Retrofit}" ) - val retrofitutil = listOf( + val RetrofitUtil = listOf( "com.squareup.okhttp3:logging-interceptor:${Versions.Network.OkHttp}", "com.squareup.retrofit2:converter-jackson:${Versions.Network.Retrofit}" ) - val essential = listOf( - "androidx.core:core-ktx:${Versions.Essential.CoreKtx}", - "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.Essential.Coroutines}" + val Util = listOf( + "io.github.jisungbin:erratum:${Versions.Util.Erratum}", + "io.github.jisungbin:logeukes:${Versions.Util.Logeukes}", + "io.github.ParkSangGwon:tedkeyboardobserver:${Versions.Util.KeyboardObserver}" ) - val ui = listOf( - "io.github.jisungbin:timelineview:${Versions.Ui.TimeLineView}", - "com.google.android.material:material:${Versions.Ui.Material}", - "com.airbnb.android:lottie-compose:${Versions.Ui.LottieCompose}", - "io.github.jisungbin:fancybottombar:${Versions.Ui.FancyBottomBar}", - "com.google.android.gms:play-services-oss-licenses:${Versions.OssLicense.Master}", - "androidx.constraintlayout:constraintlayout-compose:${Versions.Ui.ConstraintLayout}" - ) - - val util = listOf( - "com.jakewharton.timber:timber:${Versions.Util.Timber}", - "io.github.ParkSangGwon:tedkeyboardobserver:${Versions.Util.KeyboardObserver}", - "com.github.MindorksOpenSource:ViewColorGenerator:${Versions.Util.ViewColorGenerator}" - ) - - val room = listOf( + val Room = listOf( "androidx.room:room-ktx:${Versions.Jetpack.Room}", "androidx.room:room-runtime:${Versions.Jetpack.Room}" ) - val compose = listOf( + val Compose = listOf( "androidx.compose.ui:ui:${Versions.Compose.Master}", "androidx.compose.ui:ui-tooling:${Versions.Compose.Master}", + "com.airbnb.android:lottie-compose:${Versions.Compose.Lottie}", "androidx.compose.compiler:compiler:${Versions.Compose.Master}", "androidx.compose.material:material:${Versions.Compose.Master}", "androidx.activity:activity-compose:${Versions.Compose.Activity}", - "androidx.compose.runtime:runtime-livedata:${Versions.Compose.Master}", - "androidx.lifecycle:lifecycle-viewmodel-compose:${Versions.Lifecycle.Compose}" + "io.github.jisungbin:timelineview:${Versions.Compose.TimeLineView}", + "io.github.jisungbin:fancybottombar:${Versions.Compose.FancyBottomBar}", + "androidx.navigation:navigation-compose:${Versions.Compose.Navigation}", + "androidx.lifecycle:lifecycle-viewmodel-compose:${Versions.Compose.Lifecycle}", + "androidx.constraintlayout:constraintlayout-compose:${Versions.Compose.ConstraintLayout}" + ) + + val Debug = listOf( + "com.mocklets:pluto:${Versions.Util.Pluto}", + "com.squareup.leakcanary:leakcanary-android:${Versions.Util.LeakCanary}" ) } diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 210fc27b..9a0a17a1 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -38,11 +38,9 @@ android { } dependencies { - implementation(Dependencies.jsoup) + implementation(Dependencies.Jsoup) implementation(Dependencies.browser) - implementation(Dependencies.livedata) - implementation(Dependencies.jacksonModule) - Dependencies.essential.forEach(::api) - Dependencies.jackson.forEach(::implementation) + Dependencies.Essential.forEach(::api) + Dependencies.Jackson.forEach(::implementation) } diff --git a/common/src/main/AndroidManifest.xml b/common/src/main/AndroidManifest.xml index fd0b5041..f104f333 100644 --- a/common/src/main/AndroidManifest.xml +++ b/common/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/Config.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/BotConstant.kt similarity index 81% rename from common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/Config.kt rename to common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/BotConstant.kt index c1cda8c0..b26402ff 100644 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/Config.kt +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/BotConstant.kt @@ -7,8 +7,8 @@ * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. */ -package io.github.jisungbin.gitmessengerbot.common.config +package io.github.jisungbin.gitmessengerbot.common.constant -object Config { +object BotConstant { const val KakaoTalkDefaultPackageName = "com.kakao.talk" } diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/EditorConfig.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/EditorConstant.kt similarity index 83% rename from common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/EditorConfig.kt rename to common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/EditorConstant.kt index e3bfeb84..2572125b 100644 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/EditorConfig.kt +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/EditorConstant.kt @@ -7,9 +7,9 @@ * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. */ -package io.github.jisungbin.gitmessengerbot.common.config +package io.github.jisungbin.gitmessengerbot.common.constant -object EditorConfig { +object EditorConstant { const val HorizontalScroll = true const val FontName = "" // TODO const val FontSize = 13 diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/GithubConfig.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/GithubConstant.kt similarity index 79% rename from common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/GithubConfig.kt rename to common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/GithubConstant.kt index 1f3f3f38..977a534f 100644 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/GithubConfig.kt +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/GithubConstant.kt @@ -7,13 +7,13 @@ * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. */ -package io.github.jisungbin.gitmessengerbot.common.config +package io.github.jisungbin.gitmessengerbot.common.constant -object GithubConfig { +object GithubConstant { const val BaseUrl = "https://github.com" const val BaseApiUrl = "https://api.github.com" - const val DataPath = "${PathConfig.AppStorage}/github-data.json" + const val DataPath = "${PathConstant.AppStorage}/github-data.json" const val DefaultBranch = "main" const val DefaultRepoDescription = "Created by GitMessengerBot" diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/IntentConfig.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/IntentConstant.kt similarity index 88% rename from common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/IntentConfig.kt rename to common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/IntentConstant.kt index cab75324..681ffc87 100644 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/IntentConfig.kt +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/IntentConstant.kt @@ -7,9 +7,9 @@ * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. */ -package io.github.jisungbin.gitmessengerbot.common.config +package io.github.jisungbin.gitmessengerbot.common.constant -object IntentConfig { +object IntentConstant { const val ScriptId = "intent-script-id" const val DebugScriptId = "intent-debug-script-id" diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/PathConfig.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/PathConstant.kt similarity index 83% rename from common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/PathConfig.kt rename to common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/PathConstant.kt index 0e207932..565b1a58 100644 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/PathConfig.kt +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/PathConstant.kt @@ -7,9 +7,9 @@ * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. */ -package io.github.jisungbin.gitmessengerbot.common.config +package io.github.jisungbin.gitmessengerbot.common.constant -object PathConfig { +object PathConstant { internal const val AppStorage = "GitMessengerBot/data" const val AppData = "$AppStorage/app.json" } diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/ScriptConfig.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/ScriptConstant.kt similarity index 59% rename from common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/ScriptConfig.kt rename to common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/ScriptConstant.kt index 797f8bc9..e40c2717 100644 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/config/ScriptConfig.kt +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/constant/ScriptConstant.kt @@ -7,28 +7,28 @@ * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. */ -package io.github.jisungbin.gitmessengerbot.common.config +package io.github.jisungbin.gitmessengerbot.common.constant import io.github.jisungbin.gitmessengerbot.common.script.getScriptSuffix import io.github.jisungbin.gitmessengerbot.common.script.toScriptLangName import kotlin.random.Random @Suppress("FunctionName") -object ScriptConfig { +object ScriptConstant { const val DebugAllBot = -1 const val EvalId = -2 const val DefaultResponseFunctionName = "onMessage" - const val DebugAllPath = "${PathConfig.AppStorage}/debug" + const val DebugAllPath = "${PathConstant.AppStorage}/debug" fun DebugDataPath(scriptId: Int) = - "${PathConfig.AppStorage}/debug/$scriptId/${Random.nextInt()}.json" + "${PathConstant.AppStorage}/debug/$scriptId/${Random.nextInt()}.json" fun ScriptPath(name: String, lang: Int) = - "${PathConfig.AppStorage}/scripts/${lang.toScriptLangName()}/$name.${lang.getScriptSuffix()}" + "${PathConstant.AppStorage}/scripts/${lang.toScriptLangName()}/$name.${lang.getScriptSuffix()}" - fun ScriptListPath(lang: Int) = "${PathConfig.AppStorage}/scripts/${lang.toScriptLangName()}" + fun ScriptListPath(lang: Int) = "${PathConstant.AppStorage}/scripts/${lang.toScriptLangName()}" fun ScriptDataPath(name: String, lang: Int) = - "${PathConfig.AppStorage}/scripts/${lang.toScriptLangName()}/$name-data.json" + "${PathConstant.AppStorage}/scripts/${lang.toScriptLangName()}/$name-data.json" } diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/exception/ExceptionBuilder.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/exception/ExceptionBuilder.kt index f73b49ea..916047f6 100644 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/exception/ExceptionBuilder.kt +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/exception/ExceptionBuilder.kt @@ -9,6 +9,8 @@ package io.github.jisungbin.gitmessengerbot.common.exception +class TodoException(where: String) : Exception("$where 은 아직 개발되지 않은 기능입니다.") + class CoreException(override val message: String?) : Exception() class DataGithubException(override val message: String?) : Exception() diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/LiveData.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/LiveData.kt deleted file mode 100644 index 6e175c58..00000000 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/LiveData.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * GitMessengerBot © 2021 지성빈 & 구환. all rights reserved. - * GitMessengerBot license is under the GPL-3.0. - * - * [LiveData.kt] created by Ji Sungbin on 21. 8. 30. 오후 5:06 - * - * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. - */ - -package io.github.jisungbin.gitmessengerbot.common.extension - -import androidx.lifecycle.MutableLiveData - -fun MutableLiveData>.clear() { - value = emptyList() -} - -fun MutableLiveData>.removeAll(predicate: (T) -> Boolean) { - val value = this.value?.toMutableList() ?: return - value.removeAll(predicate) - notifyDataSetChanged(value) -} - -fun MutableLiveData>.removeIf(predicate: (T) -> Boolean) { - val value = this.value?.toMutableList() ?: return - value.removeIf(predicate) - notifyDataSetChanged(value) -} - -@PublishedApi -internal fun MutableLiveData>.notifyDataSetChanged(value: List) { - this.value = value -} - -inline fun MutableLiveData>.edit(action: MutableList.() -> Unit) { - val items = value?.toMutableList() ?: return - action(items) - notifyDataSetChanged(items) -} diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/Result.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/Result.kt new file mode 100644 index 00000000..2298c738 --- /dev/null +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/Result.kt @@ -0,0 +1,21 @@ +/* + * GitMessengerBot © 2021 지성빈 & 구환. all rights reserved. + * GitMessengerBot license is under the GPL-3.0. + * + * [Result.kt] created by Ji Sungbin on 21. 11. 7. 오후 8:33 + * + * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. + */ + +package io.github.jisungbin.gitmessengerbot.common.extension + +inline fun Result.doWhen( + onSuccess: (result: T) -> Unit, + onFailure: (throwable: Throwable) -> Unit +) { + if (isSuccess) { + onSuccess(getOrNull()!!) + } else { + onFailure(exceptionOrNull()!!) + } +} diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/StateFlow.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/StateFlow.kt new file mode 100644 index 00000000..f5628d71 --- /dev/null +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/StateFlow.kt @@ -0,0 +1,39 @@ +/* + * GitMessengerBot © 2021 지성빈 & 구환. all rights reserved. + * GitMessengerBot license is under the GPL-3.0. + * + * [StateFlow.kt] created by Ji Sungbin on 21. 8. 30. 오후 5:06 + * + * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. + */ + +package io.github.jisungbin.gitmessengerbot.common.extension + +import kotlinx.coroutines.flow.MutableStateFlow + +fun MutableStateFlow>.clear() { + value = emptyList() +} + +fun MutableStateFlow>.removeAll(predicate: (T) -> Boolean) { + val value = this.value.toMutableList() + value.removeAll(predicate) + notifyDataSetChanged(value) +} + +fun MutableStateFlow>.removeIf(predicate: (T) -> Boolean) { + val value = this.value.toMutableList() + value.removeIf(predicate) + notifyDataSetChanged(value) +} + +@PublishedApi +internal fun MutableStateFlow>.notifyDataSetChanged(value: List) { + this.value = value +} + +inline fun MutableStateFlow>.edit(action: MutableList.() -> Unit) { + val items = value.toMutableList() + action(items) + notifyDataSetChanged(items) +} diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/Activity.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/Throwable.kt similarity index 55% rename from common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/Activity.kt rename to common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/Throwable.kt index 8db40e2f..e3947d7e 100644 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/Activity.kt +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/Throwable.kt @@ -2,16 +2,11 @@ * GitMessengerBot © 2021 지성빈 & 구환. all rights reserved. * GitMessengerBot license is under the GPL-3.0. * - * [Activity.kt] created by Ji Sungbin on 21. 8. 30. 오후 5:05 + * [Throwable.kt] created by Ji Sungbin on 21. 11. 7. 오후 11:49 * * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. */ package io.github.jisungbin.gitmessengerbot.common.extension -import android.app.Activity -import android.widget.Toast - -fun Activity.toast(message: String, length: Int = Toast.LENGTH_SHORT) { - toast(this, message, length) -} +fun Throwable.toException() = Exception(this) diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/Unit.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/Unit.kt index 21835b77..c2ce2dae 100644 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/Unit.kt +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/Unit.kt @@ -9,9 +9,9 @@ package io.github.jisungbin.gitmessengerbot.common.extension -import android.os.Handler -import android.os.Looper +import kotlinx.coroutines.delay -inline fun doDelay(ms: Long, crossinline action: () -> Unit) { - Handler(Looper.getMainLooper()).postDelayed({ action() }, ms) +suspend fun doDelay(ms: Long, block: () -> Unit) { + delay(ms) + block() } diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/json.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/json.kt index ea1547a8..c55a205d 100644 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/json.kt +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/json.kt @@ -21,7 +21,7 @@ internal val mapper by lazy { } inline fun String.toModel(): T = mapper.readValue(this, T::class.java) - ?: throw CommonException("Error occur when convert string to json-object. ($this)") + ?: throw CommonException("문자열을 json 모델로 바꾸는데 오류가 발생했어요.\n\n($this)") fun Any.toJsonString() = mapper.writeValueAsString(this) - ?: throw CommonException("Error occur when convert json-object to string. ($this)") + ?: throw CommonException("json 모델을 문자열로 바꾸는데 오류가 발생했어요.\n\n($this)") diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/runif.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/runIf.kt similarity index 86% rename from common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/runif.kt rename to common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/runIf.kt index 6e0067d3..11f8e8be 100644 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/runif.kt +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/runIf.kt @@ -2,7 +2,7 @@ * GitMessengerBot © 2021 지성빈 & 구환. all rights reserved. * GitMessengerBot license is under the GPL-3.0. * - * [runif.kt] created by Ji Sungbin on 21. 8. 30. 오후 5:06 + * [runIf.kt] created by Ji Sungbin on 21. 8. 30. 오후 5:06 * * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. */ diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/UI.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/toast.kt similarity index 69% rename from common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/UI.kt rename to common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/toast.kt index 72ec4e75..f9b2b888 100644 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/UI.kt +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/extension/toast.kt @@ -2,7 +2,7 @@ * GitMessengerBot © 2021 지성빈 & 구환. all rights reserved. * GitMessengerBot license is under the GPL-3.0. * - * [UI.kt] created by Ji Sungbin on 21. 8. 30. 오후 5:06 + * [toast.kt] created by Ji Sungbin on 21. 8. 30. 오후 5:06 * * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. */ @@ -13,9 +13,9 @@ import android.app.Activity import android.content.Context import android.widget.Toast -fun toast(activity: Activity, message: String, length: Int = Toast.LENGTH_SHORT) { - activity.runOnUiThread { - Toast.makeText(activity, message, length).show() +fun Activity.toast(message: String, length: Int = Toast.LENGTH_SHORT) { + runOnUiThread { + toast(this, message, length) } } diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/operator/LiveData.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/operator/LiveData.kt deleted file mode 100644 index 0727ee94..00000000 --- a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/operator/LiveData.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * GitMessengerBot © 2021 지성빈 & 구환. all rights reserved. - * GitMessengerBot license is under the GPL-3.0. - * - * [LiveData.kt] created by Ji Sungbin on 21. 8. 30. 오후 5:06 - * - * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. - */ - -package io.github.jisungbin.gitmessengerbot.common.operator - -import androidx.lifecycle.MutableLiveData - -operator fun MutableLiveData>.plusAssign(item: T) { - val value = this.value ?: emptyList() - this.value = value + listOf(item) -} - -operator fun MutableLiveData>.minusAssign(item: T) { - val value = this.value ?: emptyList() - this.value = value - listOf(item) -} diff --git a/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/operator/StateFlow.kt b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/operator/StateFlow.kt new file mode 100644 index 00000000..046bfc1b --- /dev/null +++ b/common/src/main/kotlin/io/github/jisungbin/gitmessengerbot/common/operator/StateFlow.kt @@ -0,0 +1,20 @@ +/* + * GitMessengerBot © 2021 지성빈 & 구환. all rights reserved. + * GitMessengerBot license is under the GPL-3.0. + * + * [StateFlow.kt] created by Ji Sungbin on 21. 8. 30. 오후 5:06 + * + * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. + */ + +package io.github.jisungbin.gitmessengerbot.common.operator + +import kotlinx.coroutines.flow.MutableStateFlow + +operator fun MutableStateFlow>.plusAssign(item: T) { + this.value = this.value + listOf(item) +} + +operator fun MutableStateFlow>.minusAssign(item: T) { + this.value = this.value - listOf(item) +} diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index a466b3be..738d557d 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -1,4 +1,4 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/CoreResult.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/CoreResult.kt deleted file mode 100644 index 1d5b54b5..00000000 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/CoreResult.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * GitMessengerBot © 2021 지성빈 & 구환. all rights reserved. - * GitMessengerBot license is under the GPL-3.0. - * - * [CoreResult.kt] created by Ji Sungbin on 21. 8. 28. 오후 11:18 - * - * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. - */ - -package io.github.sungbin.gitmessengerbot.core - -sealed class CoreResult { - data class Success(val response: T) : CoreResult() - data class Fail(val exception: Exception) : CoreResult() -} - -suspend fun CoreResult.doWhen( - onSuccess: suspend (T) -> Unit, - onFail: suspend (Exception) -> Unit, -) { - when (this) { - is CoreResult.Success -> onSuccess(response) - is CoreResult.Fail -> onFail(exception) - } -} diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/Bot.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/Bot.kt index 2ffa82c2..1f55e300 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/Bot.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/Bot.kt @@ -15,9 +15,7 @@ import android.os.Bundle import android.util.Log import androidx.core.app.NotificationCompat import androidx.core.app.RemoteInput -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import io.github.jisungbin.gitmessengerbot.common.config.ScriptConfig +import io.github.jisungbin.gitmessengerbot.common.constant.ScriptConstant import io.github.jisungbin.gitmessengerbot.common.core.Storage import io.github.jisungbin.gitmessengerbot.common.exception.CoreException import io.github.jisungbin.gitmessengerbot.common.extension.edit @@ -29,48 +27,52 @@ import io.github.sungbin.gitmessengerbot.core.Injection import io.github.sungbin.gitmessengerbot.core.bot.debug.DebugStore import io.github.sungbin.gitmessengerbot.core.bot.debug.createDebugItem import io.github.sungbin.gitmessengerbot.core.bot.script.ScriptItem +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow -@Suppress("FunctionName") object Sender { const val Bot = "Bot" + + @Suppress("FunctionName") fun User(name: String = "User") = name } object Bot { - private val _scripts = MutableLiveData(getList()) - private val scriptPowers: HashMap> = hashMapOf() - private val compileStates: HashMap> = hashMapOf() + private val _scripts = MutableStateFlow(getList()) + private val scriptPowers: HashMap> = hashMapOf() + private val compileStates: HashMap> = hashMapOf() private val scriptCompiler = Injection.Compiler.provide - val scripts get(): LiveData> = _scripts + val scripts = _scripts.asStateFlow() - fun compileScript(context: Context, script: ScriptItem) = + suspend fun compileScript(context: Context, script: ScriptItem) = scriptCompiler.process(context, script) - fun getAllScripts() = scripts.value ?: emptyList() + fun getAllScripts() = scripts.value - fun getCompiledScripts() = _scripts.value?.filter { it.compiled } ?: emptyList() + fun getCompiledScripts() = _scripts.value.filter { it.compiled } - fun getRunnableScripts() = _scripts.value?.filter { it.isRunnable } ?: emptyList() + fun getRunnableScripts() = _scripts.value.filter { it.isRunnable } - fun getScriptPower(script: ScriptItem): LiveData = - scriptPowers[script.id] - ?: throw CoreException("There is no ${script.id} key in scriptPowers.") + fun getScriptPower(script: ScriptItem) = scriptPowers[script.id]?.asStateFlow() + ?: throw CoreException("scriptPowers에 ${script.id} 키가 없어요.") - fun getCompileState(script: ScriptItem): LiveData = - scriptPowers[script.id] - ?: throw CoreException("There is no ${script.id} key in compileStates.") + fun getCompileState(script: ScriptItem) = compileStates[script.id]?.asStateFlow() + ?: throw CoreException("compileStates에 ${script.id} 키가 없어요.") fun scriptDataSave(script: ScriptItem) { _scripts.edit { removeIf { it.id == script.id } add(script) } - Storage.write(ScriptConfig.ScriptDataPath(script.name, script.lang), script.toJsonString()) + Storage.write( + ScriptConstant.ScriptDataPath(script.name, script.lang), + script.toJsonString() + ) } fun scriptCodeSave(script: ScriptItem, code: String) { - Storage.write(ScriptConfig.ScriptPath(script.name, script.lang), code) + Storage.write(ScriptConstant.ScriptPath(script.name, script.lang), code) } fun addScript(script: ScriptItem) { @@ -88,7 +90,7 @@ object Bot { val sendIntent = Intent() val messageBundle = Bundle() val remoteInputs = - session.remoteInputs ?: throw CoreException("remoteInputs cannot be null.") + session.remoteInputs ?: throw CoreException("remoteInputs가 null 이에요.") for (inputable in remoteInputs) { messageBundle.putCharSequence(inputable.resultKey, message) } @@ -114,14 +116,14 @@ object Bot { return } v8.locker.acquire() - if (script.id == ScriptConfig.EvalId) { + if (script.id == ScriptConstant.EvalId) { val result = v8.executeScript(message).toString() - DebugStore.add(createDebugItem(ScriptConfig.EvalId, result, "null", Sender.Bot)) + DebugStore.add(createDebugItem(ScriptConstant.EvalId, result, "null", Sender.Bot)) } else { val arguments = listOf(room, message, sender, isGroupChat, "null", isDebugMode) v8.executeJSFunction( - ScriptConfig.DefaultResponseFunctionName, + ScriptConstant.DefaultResponseFunctionName, *arguments.toTypedArray() ) } @@ -135,10 +137,11 @@ object Bot { private fun getList(): List { val scripts = mutableListOf() repeat(4) { lang -> // 스크립트 코드파일이 아니라, 스크립트 정보 파일을 읽어와야함 - Storage.fileList(ScriptConfig.ScriptListPath(lang)).filter { it.path.endsWith(".json") } + Storage.fileList(ScriptConstant.ScriptListPath(lang)) + .filter { it.path.endsWith(".json") } .forEach { scriptDataFile -> val scriptData = Storage.read(scriptDataFile.path, null) - ?: throw CoreException("$scriptDataFile file is null.") + ?: throw CoreException("$scriptDataFile 파일이 null 이에요.") val script: ScriptItem = scriptData.toModel() if (script.compiled) { if (StackManager.v8[script.id] == null) { diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/api/BotApi.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/api/BotApi.kt index ab84ee0e..5d0a266b 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/api/BotApi.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/api/BotApi.kt @@ -22,7 +22,7 @@ internal class BotApi(private val context: Context, private val scriptId: Int) { private val showAll = "\u200b".repeat(500) private fun getReplySession(room: String) = StackManager.sessions[room] - ?: throw CoreException("There is no $scriptId key in StackManager.sessions.") + ?: throw CoreException("StackManager.sessions에 $scriptId 키가 없어요.") fun reply(room: String, message: String, isDebugMode: Boolean) { if (!isDebugMode) { diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/api/UI.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/api/UI.kt index 84898eab..d74cdacb 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/api/UI.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/api/UI.kt @@ -2,7 +2,7 @@ * GitMessengerBot © 2021 지성빈 & 구환. all rights reserved. * GitMessengerBot license is under the GPL-3.0. * - * [UI.kt] created by Ji Sungbin on 21. 7. 10. 오전 11:35. + * [toast.kt] created by Ji Sungbin on 21. 7. 10. 오전 11:35. * * Please see: https://github.com/GitMessengerBot/GitMessengerBot-Android/blob/master/LICENSE. */ @@ -11,7 +11,7 @@ package io.github.sungbin.gitmessengerbot.core.bot.api import android.content.Context -// TODO: activity 메모리 누수 해결 +// TODO: context 메모리 누수 해결 internal class UI(private val context: Context) { // TODO fun toast(message: String) { io.github.jisungbin.gitmessengerbot.common.extension.toast(context, message) diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/debug/DebugStore.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/debug/DebugStore.kt index 89ee3efa..5b9f043e 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/debug/DebugStore.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/debug/DebugStore.kt @@ -9,9 +9,7 @@ package io.github.sungbin.gitmessengerbot.core.bot.debug -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import io.github.jisungbin.gitmessengerbot.common.config.ScriptConfig +import io.github.jisungbin.gitmessengerbot.common.constant.ScriptConstant import io.github.jisungbin.gitmessengerbot.common.core.Storage import io.github.jisungbin.gitmessengerbot.common.exception.CoreException import io.github.jisungbin.gitmessengerbot.common.extension.clear @@ -19,47 +17,46 @@ import io.github.jisungbin.gitmessengerbot.common.extension.removeAll import io.github.jisungbin.gitmessengerbot.common.extension.toJsonString import io.github.jisungbin.gitmessengerbot.common.extension.toModel import io.github.jisungbin.gitmessengerbot.common.operator.plusAssign +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow -@Suppress("ObjectPropertyName") object DebugStore { - private val _items = MutableLiveData(getList()) + private val _items = MutableStateFlow(getList()) + val items = _items.asStateFlow() - val items: LiveData> get() = _items - val itemsValue get(): List = items.value ?: emptyList() - - fun getByScriptId(id: Int) = itemsValue.filter { id == id } + fun getByScriptId(id: Int) = items.value.filter { id == id } fun add(item: DebugItem) { _items += item - Storage.write(ScriptConfig.DebugDataPath(item.scriptId), item.toJsonString()) + Storage.write(ScriptConstant.DebugDataPath(item.scriptId), item.toJsonString()) } fun removeAll() { _items.clear() - Storage.deleteAll(ScriptConfig.DebugAllPath) + Storage.deleteAll(ScriptConstant.DebugAllPath) } fun removeAll(scriptId: Int) { - if (scriptId == ScriptConfig.DebugAllBot) { - _items.removeAll { it.scriptId != ScriptConfig.EvalId } - Storage.fileList(ScriptConfig.DebugAllPath).forEach { debugFolder -> - if (debugFolder.path != ScriptConfig.DebugDataPath(ScriptConfig.EvalId)) { + if (scriptId == ScriptConstant.DebugAllBot) { + _items.removeAll { it.scriptId != ScriptConstant.EvalId } + Storage.fileList(ScriptConstant.DebugAllPath).forEach { debugFolder -> + if (debugFolder.path != ScriptConstant.DebugDataPath(ScriptConstant.EvalId)) { debugFolder.deleteRecursively() } } } else { _items.removeAll { it.scriptId == scriptId } - Storage.deleteAll(ScriptConfig.DebugDataPath(scriptId)) + Storage.deleteAll(ScriptConstant.DebugDataPath(scriptId)) } } private fun getList(): List { val debugs = mutableListOf() - Storage.fileList(ScriptConfig.DebugAllPath).forEach { debugFolder -> + Storage.fileList(ScriptConstant.DebugAllPath).forEach { debugFolder -> Storage.fileList(debugFolder.path).forEach { debugFile -> debugs.add( Storage.read(debugFile.path, null)?.toModel() - ?: throw CoreException("$debugFile file is null.") + ?: throw CoreException("$debugFile 파일이 없어요.") ) } } diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/ScriptItem.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/ScriptItem.kt index 75b15bb6..25500024 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/ScriptItem.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/ScriptItem.kt @@ -9,7 +9,7 @@ package io.github.sungbin.gitmessengerbot.core.bot.script -import io.github.jisungbin.gitmessengerbot.common.config.ScriptConfig +import io.github.jisungbin.gitmessengerbot.common.constant.ScriptConstant import io.github.jisungbin.gitmessengerbot.common.core.Storage import io.github.jisungbin.gitmessengerbot.common.exception.CoreException import io.github.jisungbin.gitmessengerbot.common.extension.toJsonString @@ -30,16 +30,16 @@ data class ScriptItem( private val defaultCode = lang.getScriptDefaultCode() fun add() { - Storage.write(ScriptConfig.ScriptPath(name, lang), defaultCode) - Storage.write(ScriptConfig.ScriptDataPath(name, lang), toJsonString()) + Storage.write(ScriptConstant.ScriptPath(name, lang), defaultCode) + Storage.write(ScriptConstant.ScriptDataPath(name, lang), toJsonString()) } fun delete() { - Storage.delete(ScriptConfig.ScriptPath(name, lang)) - Storage.delete(ScriptConfig.ScriptDataPath(name, lang)) + Storage.delete(ScriptConstant.ScriptPath(name, lang)) + Storage.delete(ScriptConstant.ScriptDataPath(name, lang)) } - fun getCode() = Storage.read(ScriptConfig.ScriptPath(name, lang), defaultCode) + fun getCode() = Storage.read(ScriptConstant.ScriptPath(name, lang), defaultCode) ?: throw CoreException("The script's code cannot be null. (ScriptId: $id)") } diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/compiler/repo/ScriptCompiler.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/compiler/repo/ScriptCompiler.kt index de062ca0..967835e8 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/compiler/repo/ScriptCompiler.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/compiler/repo/ScriptCompiler.kt @@ -10,10 +10,8 @@ package io.github.sungbin.gitmessengerbot.core.bot.script.compiler.repo import android.content.Context -import io.github.sungbin.gitmessengerbot.core.CoreResult import io.github.sungbin.gitmessengerbot.core.bot.script.ScriptItem -import kotlinx.coroutines.flow.Flow internal interface ScriptCompiler { - fun process(context: Context, script: ScriptItem): Flow> + suspend fun process(context: Context, script: ScriptItem): Result } diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/compiler/repo/ScriptCompilerImpl.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/compiler/repo/ScriptCompilerImpl.kt index a5cc4793..3db86044 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/compiler/repo/ScriptCompilerImpl.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/compiler/repo/ScriptCompilerImpl.kt @@ -12,10 +12,10 @@ package io.github.sungbin.gitmessengerbot.core.bot.script.compiler.repo import android.content.Context import com.eclipsesource.v8.V8 import com.eclipsesource.v8.V8Object -import io.github.jisungbin.gitmessengerbot.common.config.ScriptConfig -import io.github.jisungbin.gitmessengerbot.common.exception.CoreException +import io.github.jisungbin.gitmessengerbot.common.constant.ScriptConstant +import io.github.jisungbin.gitmessengerbot.common.exception.TodoException +import io.github.jisungbin.gitmessengerbot.common.extension.doWhen import io.github.jisungbin.gitmessengerbot.common.script.ScriptLang -import io.github.sungbin.gitmessengerbot.core.CoreResult import io.github.sungbin.gitmessengerbot.core.bot.Bot import io.github.sungbin.gitmessengerbot.core.bot.StackManager import io.github.sungbin.gitmessengerbot.core.bot.api.BotApi @@ -23,13 +23,10 @@ import io.github.sungbin.gitmessengerbot.core.bot.api.Log import io.github.sungbin.gitmessengerbot.core.bot.api.UI import io.github.sungbin.gitmessengerbot.core.bot.script.ScriptItem import io.github.sungbin.gitmessengerbot.core.bot.script.ts2js.repo.Ts2JsRepo -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.callbackFlow -import kotlinx.coroutines.flow.collect +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine internal class ScriptCompilerImpl(private val ts2Js: Ts2JsRepo) : ScriptCompiler { - private fun compileJavaScript( context: Context, script: ScriptItem, @@ -103,11 +100,11 @@ internal class ScriptCompilerImpl(private val ts2Js: Ts2JsRepo) : ScriptCompiler StackManager.v8[script.id] = v8 script.compiled = true v8.locker.release() - CoreResult.Success(Unit) + Result.success(Unit) } catch (exception: Exception) { script.power = false script.compiled = false - CoreResult.Fail(exception) + Result.failure(exception) } @Suppress("DEPRECATION") @@ -132,42 +129,40 @@ internal class ScriptCompilerImpl(private val ts2Js: Ts2JsRepo) : ScriptCompiler api.release() } - @OptIn(ExperimentalCoroutinesApi::class) - override fun process(context: Context, script: ScriptItem) = callbackFlow { - when (script.lang) { - ScriptLang.TypeScript -> { - ts2Js - .convert(script.getCode()) - .collect { ts2JsResult -> - when (ts2JsResult) { - is CoreResult.Success -> { - val jsCode = ts2JsResult.response.jsCode + override suspend fun process(context: Context, script: ScriptItem): Result = + suspendCoroutine { continuation -> + when (script.lang) { + ScriptLang.TypeScript -> suspend { + ts2Js + .convert(script.getCode()) + .doWhen( + onSuccess = { ts2JsResult -> + val jsCode = ts2JsResult.jsCode android.util.Log.i("ts2JsResult", jsCode) - trySend(compileJavaScript(context, script, jsCode)) - } - is CoreResult.Fail -> { + continuation.resume( + compileJavaScript(context, script, jsCode) + ) + }, + onFailure = { exception -> script.power = false script.compiled = false - trySend(CoreResult.Fail(ts2JsResult.exception)) + continuation.resume(Result.failure(exception)) } - } - } - } - ScriptLang.JavaScript -> { - trySend(compileJavaScript(context, script, script.getCode())) - } - ScriptLang.Python -> { // todo - trySend(CoreResult.Fail(CoreException("Python build is TODO."))) - } - ScriptLang.Simple -> { // todo - trySend(CoreResult.Fail(CoreException("SimpleLang build is TODO."))) + ) + } + ScriptLang.JavaScript -> { + continuation.resume(compileJavaScript(context, script, script.getCode())) + } + ScriptLang.Python -> { // todo + continuation.resume(Result.failure(TodoException("파이썬 언어"))) + } + ScriptLang.Simple -> { // todo + continuation.resume(Result.failure(TodoException("단자응 언어"))) + } } - } - if (script.id != ScriptConfig.EvalId) { - Bot.scriptDataSave(script) + if (script.id != ScriptConstant.EvalId) { + Bot.scriptDataSave(script) + } } - - awaitClose { close() } - } } diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/ts2js/repo/Ts2JsRepo.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/ts2js/repo/Ts2JsRepo.kt index b567d62a..29d884bd 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/ts2js/repo/Ts2JsRepo.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/ts2js/repo/Ts2JsRepo.kt @@ -9,10 +9,8 @@ package io.github.sungbin.gitmessengerbot.core.bot.script.ts2js.repo -import io.github.sungbin.gitmessengerbot.core.CoreResult import io.github.sungbin.gitmessengerbot.core.bot.script.ts2js.Ts2JsResponse -import kotlinx.coroutines.flow.Flow internal interface Ts2JsRepo { - fun convert(js: String): Flow> + suspend fun convert(js: String): Result } diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/ts2js/repo/Ts2JsRepoImpl.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/ts2js/repo/Ts2JsRepoImpl.kt index e73bb90b..00603cb7 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/ts2js/repo/Ts2JsRepoImpl.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/bot/script/ts2js/repo/Ts2JsRepoImpl.kt @@ -11,25 +11,21 @@ package io.github.sungbin.gitmessengerbot.core.bot.script.ts2js.repo import io.github.jisungbin.gitmessengerbot.common.extension.ioThread import io.github.jisungbin.gitmessengerbot.common.extension.toModel -import io.github.sungbin.gitmessengerbot.core.CoreResult import io.github.sungbin.gitmessengerbot.core.bot.script.ts2js.Ts2JsResponse -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.callbackFlow +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine import org.jsoup.Connection internal class Ts2JsRepoImpl(private val jsoup: Connection) : Ts2JsRepo { - @OptIn(ExperimentalCoroutinesApi::class) - override fun convert(js: String) = callbackFlow { - try { - ioThread { - val ts2js: Ts2JsResponse = jsoup.requestBody(js).post().text().toModel() - trySend(CoreResult.Success(ts2js)) + override suspend fun convert(js: String): Result = + suspendCoroutine { continuation -> + try { + ioThread { + val ts2js: Ts2JsResponse = jsoup.requestBody(js).post().text().toModel() + continuation.resume(Result.success(ts2js)) + } + } catch (exception: Exception) { + continuation.resume(Result.failure(exception)) } - } catch (exception: Exception) { - trySend(CoreResult.Fail(exception)) } - - awaitClose { close() } - } } diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/service/BackgroundService.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/service/BackgroundService.kt index b955c212..79e38d92 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/service/BackgroundService.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/service/BackgroundService.kt @@ -17,7 +17,7 @@ import android.content.Intent import android.os.IBinder import android.os.PowerManager import androidx.core.app.NotificationCompat -import io.github.jisungbin.gitmessengerbot.common.config.IntentConfig +import io.github.jisungbin.gitmessengerbot.common.constant.IntentConstant import io.github.jisungbin.gitmessengerbot.common.core.NotificationUtil import io.github.sungbin.gitmessengerbot.core.R @@ -45,7 +45,7 @@ class BackgroundService : Service() { ) val botPowerToggleIntent = Intent(this, NotifiactionService::class.java).apply { - putExtra(IntentConfig.NotificationAction, IntentConfig.BotPowerToggle) + putExtra(IntentConstant.NotificationAction, IntentConstant.BotPowerToggle) } val botPowerTogglePendingIntent = PendingIntent.getBroadcast( @@ -64,7 +64,7 @@ class BackgroundService : Service() { ) val botRecompileIntent = Intent(this, NotifiactionService::class.java).apply { - putExtra(IntentConfig.NotificationAction, IntentConfig.BotAllRecompile) + putExtra(IntentConstant.NotificationAction, IntentConstant.BotAllRecompile) } val botRecompilePendingIntent = PendingIntent.getBroadcast( diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/service/NotifiactionService.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/service/NotifiactionService.kt index 8d64039d..d549d7a6 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/service/NotifiactionService.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/service/NotifiactionService.kt @@ -12,15 +12,14 @@ package io.github.sungbin.gitmessengerbot.core.service import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import io.github.jisungbin.gitmessengerbot.common.config.IntentConfig +import io.github.jisungbin.gitmessengerbot.common.constant.IntentConstant +import io.github.jisungbin.gitmessengerbot.common.extension.doWhen import io.github.jisungbin.gitmessengerbot.common.extension.toast import io.github.sungbin.gitmessengerbot.core.Injection import io.github.sungbin.gitmessengerbot.core.R import io.github.sungbin.gitmessengerbot.core.bot.Bot -import io.github.sungbin.gitmessengerbot.core.doWhen import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch class NotifiactionService : BroadcastReceiver() { @@ -28,8 +27,8 @@ class NotifiactionService : BroadcastReceiver() { private val scriptCompiler = Injection.Compiler.provide override fun onReceive(context: Context?, intent: Intent?) { - when (intent?.getStringExtra(IntentConfig.NotificationAction)) { - IntentConfig.BotPowerToggle -> { + when (intent?.getStringExtra(IntentConstant.NotificationAction)) { + IntentConstant.BotPowerToggle -> { // TODO /*if (Bot.app.value.power.value) { context!!.startService(Intent(context, BackgroundService::class.java)) @@ -38,33 +37,31 @@ class NotifiactionService : BroadcastReceiver() { } Bot.scriptDataSaveAndUpdate(Bot.app.value.copy(power = mutableStateOf(!Bot.app.value.power.value)))*/ } - IntentConfig.BotAllRecompile -> { + IntentConstant.BotAllRecompile -> { CoroutineScope(Dispatchers.Default).launch { toast( context!!, context.getString(R.string.service_notification_toast_running_scripts_recompile) ) Bot.getRunnableScripts().forEach { script -> - scriptCompiler.process(context, script).collect { compileResult -> - compileResult.doWhen( - onSuccess = { - toast( - context, - context.getString(R.string.service_notification_toast_recompile_done) + scriptCompiler.process(context, script).doWhen( + onSuccess = { + toast( + context, + context.getString(R.string.service_notification_toast_recompile_done) + ) + }, + onFailure = { exception -> + toast( + context, + context.getString( + R.string.service_notification_toast_compile_error, + script.name, + exception.message ) - }, - onFail = { exception -> - toast( - context, - context.getString( - R.string.service_notification_toast_compile_error, - script.name, - exception.message - ) - ) - } - ) - } + ) + } + ) } } } diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/setting/AppConfig.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/setting/AppConfig.kt index 1c209015..0ece6f35 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/setting/AppConfig.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/setting/AppConfig.kt @@ -9,31 +9,29 @@ package io.github.sungbin.gitmessengerbot.core.setting -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import io.github.jisungbin.gitmessengerbot.common.config.PathConfig -import io.github.jisungbin.gitmessengerbot.common.config.ScriptConfig +import io.github.jisungbin.gitmessengerbot.common.constant.PathConstant +import io.github.jisungbin.gitmessengerbot.common.constant.ScriptConstant import io.github.jisungbin.gitmessengerbot.common.core.Storage -import io.github.jisungbin.gitmessengerbot.common.exception.CoreException import io.github.jisungbin.gitmessengerbot.common.extension.toJsonString import io.github.jisungbin.gitmessengerbot.common.extension.toModel import io.github.sungbin.gitmessengerbot.core.bot.StackManager import io.github.sungbin.gitmessengerbot.core.setting.model.App +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow object AppConfig { - private val _app = MutableLiveData(loadApp()) + private val _app = MutableStateFlow(loadApp()) - val app: LiveData get() = _app - val appValue: App get() = app.value ?: throw CoreException("AppConfig.app value is null.") + val app = _app.asStateFlow() + val appValue: App get() = app.value - val canUseEval: Boolean get() = StackManager.v8[ScriptConfig.EvalId] != null + val evalUsable: Boolean get() = StackManager.v8[ScriptConstant.EvalId] != null fun update(update: (App) -> App) { - var value = _app.value ?: throw CoreException("AppConfig.app value is null.") - value = update(value) - Storage.write(PathConfig.AppData, value.toJsonString()) + val value = update(appValue) + Storage.write(PathConstant.AppData, value.toJsonString()) _app.value = value } - private fun loadApp() = Storage.read(PathConfig.AppData, null)?.toModel() ?: App() + private fun loadApp() = Storage.read(PathConstant.AppData, null)?.toModel() ?: App() } diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/setting/model/App.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/setting/model/App.kt index 1d896bce..1f2fb7f4 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/setting/model/App.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/setting/model/App.kt @@ -9,24 +9,24 @@ package io.github.sungbin.gitmessengerbot.core.setting.model -import io.github.jisungbin.gitmessengerbot.common.config.Config -import io.github.jisungbin.gitmessengerbot.common.config.EditorConfig -import io.github.jisungbin.gitmessengerbot.common.config.GithubConfig -import io.github.jisungbin.gitmessengerbot.common.config.ScriptConfig +import io.github.jisungbin.gitmessengerbot.common.constant.BotConstant +import io.github.jisungbin.gitmessengerbot.common.constant.EditorConstant +import io.github.jisungbin.gitmessengerbot.common.constant.GithubConstant +import io.github.jisungbin.gitmessengerbot.common.constant.ScriptConstant import io.github.jisungbin.gitmessengerbot.common.script.ScriptLang data class App( val power: Boolean = false, val evalMode: Boolean = false, - val editorHorizontalScroll: Boolean = EditorConfig.HorizontalScroll, - val editorFontName: String = EditorConfig.FontName, - val editorFontSize: Int = EditorConfig.FontSize, - val editorAutoSave: Int = EditorConfig.AutoSave, + val editorHorizontalScroll: Boolean = EditorConstant.HorizontalScroll, + val editorFontName: String = EditorConstant.FontName, + val editorFontSize: Int = EditorConstant.FontSize, + val editorAutoSave: Int = EditorConstant.AutoSave, val scriptDefaultCode: ScriptDefaultCode = ScriptDefaultCode(), val scriptDefaultLang: Int = ScriptLang.TypeScript, - val scriptResponseFunctionName: String = ScriptConfig.DefaultResponseFunctionName, - val gitDefaultBranch: String = GithubConfig.DefaultBranch, - val gitDefaultCommitMessage: String = GithubConfig.DefaultCommitMessage, + val scriptResponseFunctionName: String = ScriptConstant.DefaultResponseFunctionName, + val gitDefaultBranch: String = GithubConstant.DefaultBranch, + val gitDefaultCommitMessage: String = GithubConstant.DefaultCommitMessage, val gitDefaultRepoOptions: RepoOptions = RepoOptions(), - val kakaoTalkPackageNames: List = listOf(Config.KakaoTalkDefaultPackageName), + val kakaoTalkPackageNames: List = listOf(BotConstant.KakaoTalkDefaultPackageName), ) diff --git a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/setting/model/ScriptDefaultCode.kt b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/setting/model/ScriptDefaultCode.kt index fb613083..524c0b3c 100644 --- a/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/setting/model/ScriptDefaultCode.kt +++ b/core/src/main/kotlin/io/github/sungbin/gitmessengerbot/core/setting/model/ScriptDefaultCode.kt @@ -9,12 +9,12 @@ package io.github.sungbin.gitmessengerbot.core.setting.model -import io.github.jisungbin.gitmessengerbot.common.config.ScriptConfig +import io.github.jisungbin.gitmessengerbot.common.constant.ScriptConstant // TODO: sim data class ScriptDefaultCode( - var js: String = "const ${ScriptConfig.DefaultResponseFunctionName} = (room, message, sender, isGroupChat, profileImageBase64, isDebugMode) => {\n\t\tconst reply = (message) => {\n\t\t\t\tBot.reply(room, message, isDebugMode);\n\t\t}\n}", - var ts: String = "const ${ScriptConfig.DefaultResponseFunctionName} = (room: string, message: string, sender: string, isGroupChat: boolean, profileImageBase64: string, isDebugMode: Boolean) => {\n\t\tconst reply = (message: String) => {\n\t\t\t\tBot.reply(room, message, isDebugMode);\n\t\t}\n}", - var py: String = "def ${ScriptConfig.DefaultResponseFunctionName}(self, room, message, sender, isGroupChat, profileImageBase64):\n\t\t\t\t", + var js: String = "const ${ScriptConstant.DefaultResponseFunctionName} = (room, message, sender, isGroupChat, profileImageBase64, isDebugMode) => {\n\t\tconst reply = (message) => {\n\t\t\t\tBot.reply(room, message, isDebugMode);\n\t\t}\n}", + var ts: String = "const ${ScriptConstant.DefaultResponseFunctionName} = (room: string, message: string, sender: string, isGroupChat: boolean, profileImageBase64: string, isDebugMode: Boolean) => {\n\t\tconst reply = (message: String) => {\n\t\t\t\tBot.reply(room, message, isDebugMode);\n\t\t}\n}", + var py: String = "def ${ScriptConstant.DefaultResponseFunctionName}(self, room, message, sender, isGroupChat, profileImageBase64):\n\t\t\t\t", var sim: String = "todo", ) diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 9ee420ca..453ed5f4 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -1,4 +1,4 @@ -