From 37443136f367363eae2c2c9987d2dcc908615ba7 Mon Sep 17 00:00:00 2001 From: hyeseon Date: Sat, 1 Feb 2025 17:08:27 +0900 Subject: [PATCH 1/6] [feat/#10] Implement WebInterface (WebBridge) for communication between Android and WebView --- .../nexters/misik/domain/WebBridgeContract.kt | 9 ++++ .../java/com/nexters/misik/webview/MyClass.kt | 3 -- .../nexters/misik/webview/WebBridgeImpl.kt | 29 ++++++++++++ .../nexters/misik/webview/WebBridgeModule.kt | 26 +++++++++++ .../com/nexters/misik/webview/WebInterface.kt | 44 +++++++++++++++++++ 5 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 domain/src/main/java/com/nexters/misik/domain/WebBridgeContract.kt delete mode 100644 feature/webview/src/main/java/com/nexters/misik/webview/MyClass.kt create mode 100644 feature/webview/src/main/java/com/nexters/misik/webview/WebBridgeImpl.kt create mode 100644 feature/webview/src/main/java/com/nexters/misik/webview/WebBridgeModule.kt create mode 100644 feature/webview/src/main/java/com/nexters/misik/webview/WebInterface.kt diff --git a/domain/src/main/java/com/nexters/misik/domain/WebBridgeContract.kt b/domain/src/main/java/com/nexters/misik/domain/WebBridgeContract.kt new file mode 100644 index 0000000..8522f30 --- /dev/null +++ b/domain/src/main/java/com/nexters/misik/domain/WebBridgeContract.kt @@ -0,0 +1,9 @@ +package com.nexters.misik.domain + +interface WebBridgeContract { + fun openCamera() + fun openGallery() + fun share(content: String) + fun createReview(ocrText: String, hashTags: List, reviewStyle: String) + fun copy(review: String) +} diff --git a/feature/webview/src/main/java/com/nexters/misik/webview/MyClass.kt b/feature/webview/src/main/java/com/nexters/misik/webview/MyClass.kt deleted file mode 100644 index f7a6d57..0000000 --- a/feature/webview/src/main/java/com/nexters/misik/webview/MyClass.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.nexters.misik.webview - -class MyClass diff --git a/feature/webview/src/main/java/com/nexters/misik/webview/WebBridgeImpl.kt b/feature/webview/src/main/java/com/nexters/misik/webview/WebBridgeImpl.kt new file mode 100644 index 0000000..09f5733 --- /dev/null +++ b/feature/webview/src/main/java/com/nexters/misik/webview/WebBridgeImpl.kt @@ -0,0 +1,29 @@ +package com.nexters.misik.webview + +import android.content.Context +import com.nexters.misik.domain.WebBridgeContract +import javax.inject.Inject + +class WebBridgeImpl @Inject constructor( + private val context: Context, +) : WebBridgeContract { + override fun openCamera() { + // 카메라 실행 + } + + override fun openGallery() { + // 갤러리 실행 + } + + override fun share(content: String) { + // 공유 + } + + override fun createReview(ocrText: String, hashTags: List, reviewStyle: String) { + // 리뷰 생성 + } + + override fun copy(review: String) { + // 텍스트 복사 + } +} diff --git a/feature/webview/src/main/java/com/nexters/misik/webview/WebBridgeModule.kt b/feature/webview/src/main/java/com/nexters/misik/webview/WebBridgeModule.kt new file mode 100644 index 0000000..69349f6 --- /dev/null +++ b/feature/webview/src/main/java/com/nexters/misik/webview/WebBridgeModule.kt @@ -0,0 +1,26 @@ +package com.nexters.misik.webview + +import android.app.Application +import android.content.Context +import com.nexters.misik.domain.WebBridgeContract +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent + +@Module +@InstallIn(SingletonComponent::class) +object WebBridgeModule { + + @Provides + fun provideWebBridgeImpl(context: Context): WebBridgeContract { + return WebBridgeImpl(context) + } + + @Provides + fun provideContext(application: Application): Context { + return application.applicationContext + } + +} + diff --git a/feature/webview/src/main/java/com/nexters/misik/webview/WebInterface.kt b/feature/webview/src/main/java/com/nexters/misik/webview/WebInterface.kt new file mode 100644 index 0000000..02f9276 --- /dev/null +++ b/feature/webview/src/main/java/com/nexters/misik/webview/WebInterface.kt @@ -0,0 +1,44 @@ +package com.nexters.misik.webview + +import android.webkit.JavascriptInterface +import com.nexters.misik.domain.WebBridgeContract +import org.json.JSONObject +import javax.inject.Inject + +class WebInterface @Inject constructor( + private val bridge: WebBridgeContract, +) { + + @JavascriptInterface + fun openCamera() { + bridge.openCamera() + } + + @JavascriptInterface + fun openGallery() { + bridge.openGallery() + } + + @JavascriptInterface + fun share(content: String) { + bridge.share(content) + } + + @JavascriptInterface + fun createReview(json: String) { + val jsonObject = JSONObject(json) + val ocrText = jsonObject.getString("ocrText") + val hashTags = jsonObject.getJSONArray("hashTag").let { array -> + List(array.length()) { array.getString(it) } + } + val reviewStyle = jsonObject.getString("reviewStyle") + bridge.createReview(ocrText, hashTags, reviewStyle) + } + + @JavascriptInterface + fun copy(json: String) { + val jsonObject = JSONObject(json) + val review = jsonObject.getString("review") + bridge.copy(review) + } +} From d143796e443c4590040bb0a429ed3390e75993bd Mon Sep 17 00:00:00 2001 From: hyeseon Date: Sat, 1 Feb 2025 17:08:43 +0900 Subject: [PATCH 2/6] [feat/#10] Implement WebViewScreen --- app/build.gradle.kts | 6 +- .../nexters/misik/ExampleInstrumentedTest.kt | 22 ------- app/src/main/AndroidManifest.xml | 2 +- .../java/com/nexters/misik/MainActivity.kt | 50 --------------- .../java/com/nexters/misik/ExampleUnitTest.kt | 16 ----- .../com/nexters/misik/webview/MainActivity.kt | 62 +++++++++++++++++++ 6 files changed, 68 insertions(+), 90 deletions(-) delete mode 100644 app/src/androidTest/java/com/nexters/misik/ExampleInstrumentedTest.kt delete mode 100644 app/src/main/java/com/nexters/misik/MainActivity.kt delete mode 100644 app/src/test/java/com/nexters/misik/ExampleUnitTest.kt create mode 100644 feature/webview/src/main/java/com/nexters/misik/webview/MainActivity.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7bbd037..be39169 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -9,4 +9,8 @@ plugins { android { namespace = "com.nexters.misik" -} \ No newline at end of file +} + +dependencies { + implementation(projects.feature.webview) +} diff --git a/app/src/androidTest/java/com/nexters/misik/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/nexters/misik/ExampleInstrumentedTest.kt deleted file mode 100644 index dc4d481..0000000 --- a/app/src/androidTest/java/com/nexters/misik/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.nexters.misik - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.nexters.misik_android", appContext.packageName) - } -} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 925bdbc..ca47bb6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,7 +16,7 @@ android:theme="@style/Theme.MisikAndroid" tools:targetApi="31"> diff --git a/app/src/main/java/com/nexters/misik/MainActivity.kt b/app/src/main/java/com/nexters/misik/MainActivity.kt deleted file mode 100644 index e39968c..0000000 --- a/app/src/main/java/com/nexters/misik/MainActivity.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.nexters.misik - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import com.nexters.misik.ui.theme.MisikAndroidTheme - -class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContent { - MisikAndroidTheme { - Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> - Greeting( - name = "Android", - modifier = Modifier.padding(innerPadding), - ) - } - } - } - } -} - -@Composable -fun Greeting( - name: String, - modifier: Modifier = Modifier, -) { - Text( - text = "Hello $name!", - modifier = modifier, - ) -} - -@Preview(showBackground = true) -@Composable -fun GreetingPreview() { - MisikAndroidTheme { - Greeting("Android") - } -} diff --git a/app/src/test/java/com/nexters/misik/ExampleUnitTest.kt b/app/src/test/java/com/nexters/misik/ExampleUnitTest.kt deleted file mode 100644 index dba0f4d..0000000 --- a/app/src/test/java/com/nexters/misik/ExampleUnitTest.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.nexters.misik - -import org.junit.Assert.assertEquals -import org.junit.Test - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} diff --git a/feature/webview/src/main/java/com/nexters/misik/webview/MainActivity.kt b/feature/webview/src/main/java/com/nexters/misik/webview/MainActivity.kt new file mode 100644 index 0000000..5f979f4 --- /dev/null +++ b/feature/webview/src/main/java/com/nexters/misik/webview/MainActivity.kt @@ -0,0 +1,62 @@ +package com.nexters.misik.webview + +import android.os.Bundle +import android.webkit.WebChromeClient +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.viewinterop.AndroidView +import com.nexters.misik.webview.MainActivity.Companion.WEB_URL +import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject + +@AndroidEntryPoint +class MainActivity : ComponentActivity() { + + @Inject + lateinit var webAppInterface: WebInterface + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + + setContent { + Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> + WebViewScreen(webAppInterface, modifier = Modifier.padding(innerPadding)) + } + + } + } + + companion object { + const val WEB_URL = "https://misik-web.vercel.app/" + } +} + +@Composable +fun WebViewScreen( + webAppInterface: WebInterface, + modifier: Modifier = Modifier +) { + AndroidView( + modifier = modifier, + factory = { context -> + WebView(context).apply { + settings.javaScriptEnabled = true + webViewClient = WebViewClient() + webChromeClient = WebChromeClient() + addJavascriptInterface(webAppInterface, "AndroidBridge") + loadUrl(WEB_URL) + } + } + ) +} + + From 21ee73dabf7edbcf130f88b6225f727c72fe179e Mon Sep 17 00:00:00 2001 From: hyeseon Date: Sat, 1 Feb 2025 17:09:40 +0900 Subject: [PATCH 3/6] [chore/#10] apply ktlint style --- .../main/java/com/nexters/misik/webview/MainActivity.kt | 7 ++----- .../main/java/com/nexters/misik/webview/WebBridgeModule.kt | 2 -- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/feature/webview/src/main/java/com/nexters/misik/webview/MainActivity.kt b/feature/webview/src/main/java/com/nexters/misik/webview/MainActivity.kt index 5f979f4..60cba9f 100644 --- a/feature/webview/src/main/java/com/nexters/misik/webview/MainActivity.kt +++ b/feature/webview/src/main/java/com/nexters/misik/webview/MainActivity.kt @@ -31,7 +31,6 @@ class MainActivity : ComponentActivity() { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> WebViewScreen(webAppInterface, modifier = Modifier.padding(innerPadding)) } - } } @@ -43,7 +42,7 @@ class MainActivity : ComponentActivity() { @Composable fun WebViewScreen( webAppInterface: WebInterface, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { AndroidView( modifier = modifier, @@ -55,8 +54,6 @@ fun WebViewScreen( addJavascriptInterface(webAppInterface, "AndroidBridge") loadUrl(WEB_URL) } - } + }, ) } - - diff --git a/feature/webview/src/main/java/com/nexters/misik/webview/WebBridgeModule.kt b/feature/webview/src/main/java/com/nexters/misik/webview/WebBridgeModule.kt index 69349f6..56f3f50 100644 --- a/feature/webview/src/main/java/com/nexters/misik/webview/WebBridgeModule.kt +++ b/feature/webview/src/main/java/com/nexters/misik/webview/WebBridgeModule.kt @@ -21,6 +21,4 @@ object WebBridgeModule { fun provideContext(application: Application): Context { return application.applicationContext } - } - From ce75e30b0046980c0f56754b19d9f748c208d432 Mon Sep 17 00:00:00 2001 From: hyeseon Date: Mon, 3 Feb 2025 18:09:10 +0900 Subject: [PATCH 4/6] [mod/#10] delete 'run unit tests' from ci pipeline --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7b4682c..9acceb4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,8 +51,8 @@ jobs: run: ./gradlew spotlessCheck # 6. Run Unit Tests - - name: Run Unit Tests - run: ./gradlew test +# - name: Run Unit Tests +# run: ./gradlew test # 7. Run Lint - name: Run Lint From f29c7857c4eef80a91ee40533eba6466d304022b Mon Sep 17 00:00:00 2001 From: hyeseon Date: Mon, 3 Feb 2025 19:16:24 +0900 Subject: [PATCH 5/6] [feat/#10] implement WebViewEvent, WebViewState --- .../main/java/com/nexters/misik/webview/WebViewEvent.kt | 8 ++++++++ .../main/java/com/nexters/misik/webview/WebViewState.kt | 7 +++++++ 2 files changed, 15 insertions(+) create mode 100644 feature/webview/src/main/java/com/nexters/misik/webview/WebViewEvent.kt create mode 100644 feature/webview/src/main/java/com/nexters/misik/webview/WebViewState.kt diff --git a/feature/webview/src/main/java/com/nexters/misik/webview/WebViewEvent.kt b/feature/webview/src/main/java/com/nexters/misik/webview/WebViewEvent.kt new file mode 100644 index 0000000..898b8f8 --- /dev/null +++ b/feature/webview/src/main/java/com/nexters/misik/webview/WebViewEvent.kt @@ -0,0 +1,8 @@ +package com.nexters.misik.webview + +sealed interface WebViewEvent { + data object LoadPage : WebViewEvent // 페이지 로딩 이벤트 + data object PageLoaded : WebViewEvent // 페이지 로딩 완료 이벤트 + data class JsResponse(val response: String) : WebViewEvent // JavaScript 응답 이벤트 + data class JsError(val error: String) : WebViewEvent +} diff --git a/feature/webview/src/main/java/com/nexters/misik/webview/WebViewState.kt b/feature/webview/src/main/java/com/nexters/misik/webview/WebViewState.kt new file mode 100644 index 0000000..87f18fa --- /dev/null +++ b/feature/webview/src/main/java/com/nexters/misik/webview/WebViewState.kt @@ -0,0 +1,7 @@ +package com.nexters.misik.webview + +data class WebViewState( + val isLoading: Boolean = false, + val content: String? = null, + val error: String? = null, +) From 1d072d1fa8b7ef65d011422a95b3defcfc1f5d2c Mon Sep 17 00:00:00 2001 From: hyeseon Date: Mon, 3 Feb 2025 19:17:20 +0900 Subject: [PATCH 6/6] [feat/#10] Implement WebViewScreen with MVI pattern to manage state --- .../com/nexters/misik/webview/MainActivity.kt | 31 +------ .../nexters/misik/webview/WebViewScreen.kt | 92 +++++++++++++++++++ .../nexters/misik/webview/WebViewViewModel.kt | 30 ++++++ 3 files changed, 123 insertions(+), 30 deletions(-) create mode 100644 feature/webview/src/main/java/com/nexters/misik/webview/WebViewScreen.kt create mode 100644 feature/webview/src/main/java/com/nexters/misik/webview/WebViewViewModel.kt diff --git a/feature/webview/src/main/java/com/nexters/misik/webview/MainActivity.kt b/feature/webview/src/main/java/com/nexters/misik/webview/MainActivity.kt index 60cba9f..f8f4a9f 100644 --- a/feature/webview/src/main/java/com/nexters/misik/webview/MainActivity.kt +++ b/feature/webview/src/main/java/com/nexters/misik/webview/MainActivity.kt @@ -1,19 +1,13 @@ package com.nexters.misik.webview import android.os.Bundle -import android.webkit.WebChromeClient -import android.webkit.WebView -import android.webkit.WebViewClient import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold -import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.viewinterop.AndroidView -import com.nexters.misik.webview.MainActivity.Companion.WEB_URL import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -29,31 +23,8 @@ class MainActivity : ComponentActivity() { setContent { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> - WebViewScreen(webAppInterface, modifier = Modifier.padding(innerPadding)) + WebViewScreen(webAppInterface = webAppInterface, modifier = Modifier.padding(innerPadding)) } } } - - companion object { - const val WEB_URL = "https://misik-web.vercel.app/" - } -} - -@Composable -fun WebViewScreen( - webAppInterface: WebInterface, - modifier: Modifier = Modifier, -) { - AndroidView( - modifier = modifier, - factory = { context -> - WebView(context).apply { - settings.javaScriptEnabled = true - webViewClient = WebViewClient() - webChromeClient = WebChromeClient() - addJavascriptInterface(webAppInterface, "AndroidBridge") - loadUrl(WEB_URL) - } - }, - ) } diff --git a/feature/webview/src/main/java/com/nexters/misik/webview/WebViewScreen.kt b/feature/webview/src/main/java/com/nexters/misik/webview/WebViewScreen.kt new file mode 100644 index 0000000..89e00db --- /dev/null +++ b/feature/webview/src/main/java/com/nexters/misik/webview/WebViewScreen.kt @@ -0,0 +1,92 @@ +package com.nexters.misik.webview + +import android.webkit.WebChromeClient +import android.webkit.WebResourceError +import android.webkit.WebResourceRequest +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.viewinterop.AndroidView +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import timber.log.Timber + +@Composable +fun WebViewScreen( + webAppInterface: WebInterface, + modifier: Modifier = Modifier, + viewModel: WebViewViewModel = hiltViewModel(), +) { + val state by viewModel.state.collectAsStateWithLifecycle() + + // 페이지 로딩 이벤트 발생 (WebView 로드 시작 시) + LaunchedEffect(Unit) { + viewModel.onEvent(WebViewEvent.LoadPage) + } + + Box(modifier = modifier.fillMaxSize()) { + // 로딩 상태 UI + if (state.isLoading) { + Timber.d("WebViewScreen_UiState", "Loading") + CircularProgressIndicator( + modifier = Modifier.align(Alignment.Center), + ) + } + + // 에러 상태 UI + state.error?.let { + Timber.d("WebViewScreen_UiState", "Error: $it") + Text( + text = "Error: $it", + color = Color.Red, + modifier = Modifier.align(Alignment.Center), + ) + } + + // 콘텐츠가 있을 경우, WebView를 보여줌 + if (!state.isLoading) { + Timber.d("WebViewScreen_UiState", "Loaded") + AndroidView( + modifier = Modifier.fillMaxSize(), + factory = { context -> + WebView(context).apply { + settings.javaScriptEnabled = true + webViewClient = WebViewClient() + webChromeClient = WebChromeClient() + + addJavascriptInterface(webAppInterface, "AndroidBridge") + + loadUrl("https://misik-web.vercel.app/") + + // 페이지 로딩 완료 후 이벤트 처리 + webViewClient = object : WebViewClient() { + override fun onPageFinished(view: WebView?, url: String?) { + super.onPageFinished(view, url) + viewModel.onEvent(WebViewEvent.PageLoaded) + } + + override fun onReceivedError( + view: WebView?, + request: WebResourceRequest?, + error: WebResourceError?, + ) { + super.onReceivedError(view, request, error) + // 오류 발생 시 이벤트 호출 + viewModel.onEvent(WebViewEvent.JsError("Error loading page: ${error?.description}")) + } + } + } + }, + ) + } + } +} diff --git a/feature/webview/src/main/java/com/nexters/misik/webview/WebViewViewModel.kt b/feature/webview/src/main/java/com/nexters/misik/webview/WebViewViewModel.kt new file mode 100644 index 0000000..1cc4fb8 --- /dev/null +++ b/feature/webview/src/main/java/com/nexters/misik/webview/WebViewViewModel.kt @@ -0,0 +1,30 @@ +package com.nexters.misik.webview + +import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import javax.inject.Inject + +@HiltViewModel +class WebViewViewModel @Inject constructor() : ViewModel() { + private val _state = MutableStateFlow(WebViewState()) + val state: StateFlow get() = _state + + fun onEvent(event: WebViewEvent) { + when (event) { + WebViewEvent.LoadPage -> { + _state.value = _state.value.copy(isLoading = true, error = null) + } + WebViewEvent.PageLoaded -> { + _state.value = _state.value.copy(isLoading = false, error = null) + } + is WebViewEvent.JsResponse -> { + _state.value = _state.value.copy(isLoading = false, content = event.response, error = null) + } + is WebViewEvent.JsError -> { + _state.value = _state.value.copy(isLoading = false, error = event.error) + } + } + } +}