diff --git a/client/android/compose/src/androidTest/kotlin/com/yandex/div/compose/DivViewPreview.kt b/client/android/compose/src/androidTest/kotlin/com/yandex/div/compose/DivViewPreview.kt index db23b11ef..e942deca1 100644 --- a/client/android/compose/src/androidTest/kotlin/com/yandex/div/compose/DivViewPreview.kt +++ b/client/android/compose/src/androidTest/kotlin/com/yandex/div/compose/DivViewPreview.kt @@ -20,8 +20,10 @@ import com.yandex.div2.DivEdgeInsets @Preview @Composable fun DivViewPreview() { - val divContext = DivComposeConfiguration() - .createContext(baseContext = LocalContext.current) + val divContext = DivContext( + baseContext = LocalContext.current, + configuration = DivComposeConfiguration() + ) CompositionLocalProvider(LocalContext provides divContext) { DivView(data = testData) } diff --git a/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivComposeConfiguration.kt b/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivComposeConfiguration.kt index 9deb7c322..64fdc9232 100644 --- a/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivComposeConfiguration.kt +++ b/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivComposeConfiguration.kt @@ -1,14 +1,10 @@ package com.yandex.div.compose -import android.content.Context import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import com.yandex.div.compose.actions.DivExternalActionHandler import com.yandex.div.compose.dagger.Names -import com.yandex.div.compose.dagger.`Yatagan$DivContextComponent` -import com.yandex.div.compose.internal.DivDebugConfiguration import com.yandex.div.core.annotations.ExperimentalApi -import com.yandex.div.core.annotations.InternalApi import com.yandex.div.core.expression.variables.DivVariableController import com.yandex.yatagan.Module import com.yandex.yatagan.Provides @@ -22,7 +18,7 @@ import javax.inject.Named * val configuration = DivComposeConfiguration( * reporter = MyReporter() * ) - * val divContext = configuration.createContext(baseContext = activity) + * val divContext = DivContext(baseContext = activity, configuration = configuration) * ComposeView(divContext).setContent { * DivView(data = data) * } @@ -33,10 +29,6 @@ class DivComposeConfiguration( @get:Provides val actionHandler: DivExternalActionHandler = defaultActionHandler, - @get:Provides - @property:InternalApi - val debugConfiguration: DivDebugConfiguration = DivDebugConfiguration(), - @get:Provides val fontFamilyProvider: DivFontFamilyProvider = defaultFontFamilyProvider, @@ -48,14 +40,6 @@ class DivComposeConfiguration( val variableController: DivVariableController = DivVariableController(), ) -fun DivComposeConfiguration.createContext(baseContext: Context): DivContext { - val contextComponent = `Yatagan$DivContextComponent`.builder() - .baseContext(baseContext) - .configuration(this) - .build() - return DivContext(contextComponent) -} - private val defaultActionHandler = object : DivExternalActionHandler {} private val defaultFontFamilyProvider = object : DivFontFamilyProvider { diff --git a/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivContext.kt b/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivContext.kt index 1ce6d6ceb..094ee4bc2 100644 --- a/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivContext.kt +++ b/client/android/compose/src/main/kotlin/com/yandex/div/compose/DivContext.kt @@ -1,11 +1,13 @@ package com.yandex.div.compose +import android.content.Context import android.content.ContextWrapper -import androidx.annotation.MainThread import androidx.annotation.VisibleForTesting import com.yandex.div.compose.context.DivLocalContext import com.yandex.div.compose.context.DivViewContext import com.yandex.div.compose.dagger.DivContextComponent +import com.yandex.div.compose.dagger.`Yatagan$DivContextComponent` +import com.yandex.div.compose.internal.DivDebugConfiguration import com.yandex.div.compose.internal.DivDebugFeatures import com.yandex.div.core.annotations.ExperimentalApi import com.yandex.div.core.annotations.InternalApi @@ -17,7 +19,6 @@ import com.yandex.div2.DivBase import com.yandex.div2.DivData import com.yandex.div2.DivTrigger import com.yandex.div2.DivVariable -import javax.inject.Inject /** * An implementation of [android.content.Context] that must be used for composing [DivView]s. @@ -25,13 +26,33 @@ import javax.inject.Inject * Example usage: * * val configuration = DivComposeConfiguration() - * val divContext = configuration.createContext(baseContext = activity) + * val divContext = DivContext(activity, configuration) */ @ExperimentalApi -class DivContext @Inject @MainThread internal constructor( +class DivContext private constructor( internal val component: DivContextComponent ) : ContextWrapper(component.baseContext) { + /** + * Creates a [DivContext] with provided [DivComposeConfiguration]. + */ + constructor( + baseContext: Context, + configuration: DivComposeConfiguration + ) : this(createComponent(baseContext, configuration, DivDebugConfiguration())) + + /** + * Creates a [DivContext] with provided [DivComposeConfiguration] and [DivDebugConfiguration]. + * + * Do not use this constructor in production environment. + */ + @InternalApi + constructor( + baseContext: Context, + configuration: DivComposeConfiguration, + debugConfiguration: DivDebugConfiguration + ) : this(createComponent(baseContext, configuration, debugConfiguration)) + @InternalApi @VisibleForTesting val debugFeatures: DivDebugFeatures @@ -112,3 +133,15 @@ class DivContext @Inject @MainThread internal constructor( return localComponent.context } } + +private fun createComponent( + baseContext: Context, + configuration: DivComposeConfiguration, + debugConfiguration: DivDebugConfiguration +): DivContextComponent { + return `Yatagan$DivContextComponent`.builder() + .baseContext(baseContext) + .configuration(configuration) + .debugConfiguration(debugConfiguration) + .build() +} diff --git a/client/android/compose/src/main/kotlin/com/yandex/div/compose/dagger/DivContextComponent.kt b/client/android/compose/src/main/kotlin/com/yandex/div/compose/dagger/DivContextComponent.kt index 0bf2af68b..60ed404d0 100644 --- a/client/android/compose/src/main/kotlin/com/yandex/div/compose/dagger/DivContextComponent.kt +++ b/client/android/compose/src/main/kotlin/com/yandex/div/compose/dagger/DivContextComponent.kt @@ -8,6 +8,7 @@ import com.yandex.div.compose.DivReporter import com.yandex.div.compose.actions.DivActionHandler import com.yandex.div.compose.actions.VisibilityActionTracker import com.yandex.div.compose.context.DivViewContextStorage +import com.yandex.div.compose.internal.DivDebugConfiguration import com.yandex.div.compose.internal.DivDebugFeatures import com.yandex.div.core.expression.variables.DivVariableController import com.yandex.yatagan.BindsInstance @@ -46,6 +47,9 @@ internal interface DivContextComponent { @BindsInstance fun configuration(configuration: DivComposeConfiguration): Builder + @BindsInstance + fun debugConfiguration(configuration: DivDebugConfiguration): Builder + fun build(): DivContextComponent } } diff --git a/client/android/compose/src/main/kotlin/com/yandex/div/compose/dagger/DivContextModule.kt b/client/android/compose/src/main/kotlin/com/yandex/div/compose/dagger/DivContextModule.kt index ff89a1c10..6610de424 100644 --- a/client/android/compose/src/main/kotlin/com/yandex/div/compose/dagger/DivContextModule.kt +++ b/client/android/compose/src/main/kotlin/com/yandex/div/compose/dagger/DivContextModule.kt @@ -43,7 +43,7 @@ internal object DivContextModule { context: Context, debugConfiguration: DivDebugConfiguration ): ImageLoader { - val debugImageLoader = debugConfiguration.imageLoaderProvider?.provide(context) + val debugImageLoader = debugConfiguration.imageLoaderProvider?.provide() if (debugImageLoader != null) { return debugImageLoader } diff --git a/client/android/compose/src/main/kotlin/com/yandex/div/compose/internal/DivDebugConfiguration.kt b/client/android/compose/src/main/kotlin/com/yandex/div/compose/internal/DivDebugConfiguration.kt index 5a38d7618..719414c02 100644 --- a/client/android/compose/src/main/kotlin/com/yandex/div/compose/internal/DivDebugConfiguration.kt +++ b/client/android/compose/src/main/kotlin/com/yandex/div/compose/internal/DivDebugConfiguration.kt @@ -4,10 +4,12 @@ import com.yandex.div.core.annotations.InternalApi import kotlinx.coroutines.CoroutineScope /** - * Provides debug components for [com.yandex.div.compose.DivComposeConfiguration]. + * Provides debug configuration for [com.yandex.div.compose.DivContext]. * * This class is intended for debugging and testing only. Do not use it in the production * environment. + * + * @see com.yandex.div.compose.DivContext */ @InternalApi class DivDebugConfiguration( diff --git a/client/android/compose/src/main/kotlin/com/yandex/div/compose/internal/DivDebugFeatures.kt b/client/android/compose/src/main/kotlin/com/yandex/div/compose/internal/DivDebugFeatures.kt index 0838be812..51f6e303e 100644 --- a/client/android/compose/src/main/kotlin/com/yandex/div/compose/internal/DivDebugFeatures.kt +++ b/client/android/compose/src/main/kotlin/com/yandex/div/compose/internal/DivDebugFeatures.kt @@ -11,6 +11,8 @@ import javax.inject.Inject /** * Provides access to the features not intended to be used in production environment. + * + * @see com.yandex.div.compose.DivContext.debugFeatures */ @DivContextScope @InternalApi diff --git a/client/android/compose/src/main/kotlin/com/yandex/div/compose/internal/ImageLoaderProvider.kt b/client/android/compose/src/main/kotlin/com/yandex/div/compose/internal/ImageLoaderProvider.kt index d100fce54..5d1e10225 100644 --- a/client/android/compose/src/main/kotlin/com/yandex/div/compose/internal/ImageLoaderProvider.kt +++ b/client/android/compose/src/main/kotlin/com/yandex/div/compose/internal/ImageLoaderProvider.kt @@ -1,10 +1,17 @@ package com.yandex.div.compose.internal -import android.content.Context import coil3.ImageLoader import com.yandex.div.core.annotations.InternalApi +/** + * Provides an [ImageLoader] that is used to load images inside [com.yandex.div.compose.DivView]s. + * + * This interface is intended for testing purposes only. You should not implement it in the + * production environment. + * + * @see DivDebugConfiguration + */ @InternalApi fun interface ImageLoaderProvider { - fun provide(context: Context): ImageLoader + fun provide(): ImageLoader } diff --git a/client/android/compose/src/test/kotlin/com/yandex/div/compose/DivViewRecompositionTest.kt b/client/android/compose/src/test/kotlin/com/yandex/div/compose/DivViewRecompositionTest.kt index c97d57f79..a911a846a 100644 --- a/client/android/compose/src/test/kotlin/com/yandex/div/compose/DivViewRecompositionTest.kt +++ b/client/android/compose/src/test/kotlin/com/yandex/div/compose/DivViewRecompositionTest.kt @@ -39,10 +39,13 @@ class DivViewRecompositionTest { private lateinit var divContext: DivContext @Before - fun setup() { - divContext = DivComposeConfiguration( - reporter = TestReporter() - ).createContext(baseContext = activity) + fun setUp() { + divContext = DivContext( + baseContext = activity, + configuration = DivComposeConfiguration( + reporter = TestReporter() + ) + ) } @Test diff --git a/client/android/compose/src/test/kotlin/com/yandex/div/compose/DivViewWithTriggersTest.kt b/client/android/compose/src/test/kotlin/com/yandex/div/compose/DivViewWithTriggersTest.kt index c68208dda..bfeb2abde 100644 --- a/client/android/compose/src/test/kotlin/com/yandex/div/compose/DivViewWithTriggersTest.kt +++ b/client/android/compose/src/test/kotlin/com/yandex/div/compose/DivViewWithTriggersTest.kt @@ -42,11 +42,14 @@ class DivViewWithTriggersTest { private lateinit var divContext: DivContext @Before - fun setup() { - divContext = DivComposeConfiguration( - reporter = TestReporter(), - variableController = variableController - ).createContext(baseContext = activity) + fun setUp() { + divContext = DivContext( + baseContext = activity, + configuration = DivComposeConfiguration( + reporter = TestReporter(), + variableController = variableController + ) + ) } @Test diff --git a/client/android/compose/src/test/kotlin/com/yandex/div/compose/DivViewWithVisibilityActionsTest.kt b/client/android/compose/src/test/kotlin/com/yandex/div/compose/DivViewWithVisibilityActionsTest.kt index d56fb259a..f8bacdeae 100644 --- a/client/android/compose/src/test/kotlin/com/yandex/div/compose/DivViewWithVisibilityActionsTest.kt +++ b/client/android/compose/src/test/kotlin/com/yandex/div/compose/DivViewWithVisibilityActionsTest.kt @@ -43,16 +43,17 @@ class DivViewWithVisibilityActionsTest { declare(counter, visibility) } - private val testScope = TestScope() - private val configuration = DivComposeConfiguration( - debugConfiguration = DivDebugConfiguration( - coroutineScope = testScope - ), reporter = TestReporter(), variableController = variableController ) + private val testScope = TestScope() + + private val debugConfiguration = DivDebugConfiguration( + coroutineScope = testScope + ) + @Test fun `visibility action is triggered after delay`() { setContent( @@ -271,6 +272,7 @@ class DivViewWithVisibilityActionsTest { ) { rule.setContent( configuration = configuration, + debugConfiguration = debugConfiguration, data = data(content, variables = variables) ) } diff --git a/client/android/compose/src/test/kotlin/com/yandex/div/compose/IntegrationTest.kt b/client/android/compose/src/test/kotlin/com/yandex/div/compose/IntegrationTest.kt index 188150980..2da068689 100644 --- a/client/android/compose/src/test/kotlin/com/yandex/div/compose/IntegrationTest.kt +++ b/client/android/compose/src/test/kotlin/com/yandex/div/compose/IntegrationTest.kt @@ -28,10 +28,13 @@ class IntegrationTest(testCaseParsingResult: ParsingResult) val divData = testCase.parseDivData() ?: return val variableController = DivVariableController() - val divContext = DivComposeConfiguration( - reporter = Reporter(testCase.logger), - variableController = variableController - ).createContext(baseContext = getApplicationContext()) + val divContext = DivContext( + baseContext = getApplicationContext(), + configuration = DivComposeConfiguration( + reporter = Reporter(testCase.logger), + variableController = variableController + ) + ) testCase.declareResultVariables( variables = divData.variables ?: emptyList(), diff --git a/client/android/compose/src/test/kotlin/com/yandex/div/compose/Utils.kt b/client/android/compose/src/test/kotlin/com/yandex/div/compose/Utils.kt index 07b341635..78a408251 100644 --- a/client/android/compose/src/test/kotlin/com/yandex/div/compose/Utils.kt +++ b/client/android/compose/src/test/kotlin/com/yandex/div/compose/Utils.kt @@ -4,6 +4,7 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.test.junit4.ComposeContentTestRule import com.yandex.div.compose.expressions.DivComposeExpressionResolver +import com.yandex.div.compose.internal.DivDebugConfiguration import com.yandex.div.core.expression.variables.DivVariableController import com.yandex.div.evaluable.function.GeneratedBuiltinFunctionProvider import com.yandex.div.internal.expressions.FunctionProviderDecorator @@ -22,10 +23,15 @@ internal fun createExpressionResolver( fun ComposeContentTestRule.setContent( configuration: DivComposeConfiguration, + debugConfiguration: DivDebugConfiguration = DivDebugConfiguration(), data: DivData ) { setContent { - val divContext = configuration.createContext(baseContext = LocalContext.current) + val divContext = DivContext( + baseContext = LocalContext.current, + configuration = configuration, + debugConfiguration = debugConfiguration + ) CompositionLocalProvider(LocalContext provides divContext) { DivView(data = data) } diff --git a/client/android/compose/src/test/kotlin/com/yandex/div/compose/utils/DivVariableControllerTest.kt b/client/android/compose/src/test/kotlin/com/yandex/div/compose/utils/DivVariableControllerTest.kt index 8ee855f4e..235ec9f80 100644 --- a/client/android/compose/src/test/kotlin/com/yandex/div/compose/utils/DivVariableControllerTest.kt +++ b/client/android/compose/src/test/kotlin/com/yandex/div/compose/utils/DivVariableControllerTest.kt @@ -9,10 +9,10 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.test.junit4.createComposeRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.yandex.div.compose.DivComposeConfiguration +import com.yandex.div.compose.DivContext import com.yandex.div.compose.TestReporter import com.yandex.div.compose.context.DivLocalContext import com.yandex.div.compose.context.LocalDivContext -import com.yandex.div.compose.createContext import com.yandex.div.compose.createExpressionResolver import com.yandex.div.core.expression.variables.DivVariableController import com.yandex.div.data.Variable @@ -147,11 +147,13 @@ class DivVariableControllerTest { private fun setContent(content: @Composable () -> Unit) { composeRule.setContent { - val configuration = DivComposeConfiguration( - reporter = reporter, - variableController = variableController + val divContext = DivContext( + baseContext = LocalContext.current, + configuration = DivComposeConfiguration( + reporter = reporter, + variableController = variableController + ) ) - val divContext = configuration.createContext(baseContext = LocalContext.current) CompositionLocalProvider( LocalContext provides divContext, LocalDivContext provides localContext, diff --git a/client/android/compose/src/test/kotlin/com/yandex/div/compose/views/state/ObserveActiveStateTest.kt b/client/android/compose/src/test/kotlin/com/yandex/div/compose/views/state/ObserveActiveStateTest.kt index 34277ffb2..dbf619f1c 100644 --- a/client/android/compose/src/test/kotlin/com/yandex/div/compose/views/state/ObserveActiveStateTest.kt +++ b/client/android/compose/src/test/kotlin/com/yandex/div/compose/views/state/ObserveActiveStateTest.kt @@ -9,10 +9,10 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.test.junit4.createComposeRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.yandex.div.compose.DivComposeConfiguration +import com.yandex.div.compose.DivContext import com.yandex.div.compose.TestReporter import com.yandex.div.compose.context.DivLocalContext import com.yandex.div.compose.context.LocalDivContext -import com.yandex.div.compose.createContext import com.yandex.div.compose.createExpressionResolver import com.yandex.div.core.expression.variables.DivVariableController import com.yandex.div.data.DivModelInternalApi @@ -191,11 +191,13 @@ class ObserveActiveStateTest { private fun setContent(content: @Composable () -> Unit) { composeRule.setContent { - val configuration = DivComposeConfiguration( - reporter = reporter, - variableController = variableController + val divContext = DivContext( + baseContext = LocalContext.current, + configuration = DivComposeConfiguration( + reporter = reporter, + variableController = variableController + ) ) - val divContext = configuration.createContext(baseContext = LocalContext.current) CompositionLocalProvider( LocalContext provides divContext, LocalDivContext provides localContext, diff --git a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/div/DemoRendererFacade.kt b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/div/DemoRendererFacade.kt index 2ef7c161b..f5e3257f1 100644 --- a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/div/DemoRendererFacade.kt +++ b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/div/DemoRendererFacade.kt @@ -10,7 +10,6 @@ import com.yandex.div.DivDataTag import com.yandex.div.compose.DivComposeConfiguration import com.yandex.div.compose.DivView as ComposeDivView import com.yandex.div.compose.DivContext as ComposeDivContext -import com.yandex.div.compose.createContext import com.yandex.div.core.Div2Context import com.yandex.div.core.annotations.InternalApi import com.yandex.div.core.expression.variables.DivVariableController @@ -104,10 +103,13 @@ class ComposeRendererFacade( context: Context, ) : DemoRendererFacade { - private val composeDivContext: ComposeDivContext = DivComposeConfiguration( - fontFamilyProvider = ComposeFontFamilyProvider(context), - variableController = divVariableController, - ).createContext(baseContext = context) + private val composeDivContext = ComposeDivContext( + baseContext = context, + configuration = DivComposeConfiguration( + fontFamilyProvider = ComposeFontFamilyProvider(context), + variableController = divVariableController, + ) + ) private val composeView = ComposeView(composeDivContext).apply { layoutParams = ViewGroup.LayoutParams( diff --git a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/screenshot/DivComposeScreenshotActivity.kt b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/screenshot/DivComposeScreenshotActivity.kt index b16847a96..978e6ca95 100644 --- a/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/screenshot/DivComposeScreenshotActivity.kt +++ b/client/android/divkit-demo-app/src/main/java/com/yandex/divkit/demo/screenshot/DivComposeScreenshotActivity.kt @@ -10,7 +10,6 @@ import com.yandex.div.compose.DivComposeConfiguration import com.yandex.div.compose.DivContext import com.yandex.div.compose.DivView import com.yandex.div.compose.internal.ImageLoaderProvider -import com.yandex.div.compose.createContext import com.yandex.div.compose.internal.DivDebugConfiguration import com.yandex.div.core.annotations.InternalApi import com.yandex.div.data.DivParsingEnvironment @@ -37,19 +36,22 @@ class DivComposeScreenshotActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val imageLoaderProvider = ImageLoaderProvider { context -> - ImageLoader.Builder(context = context) + val imageLoaderProvider = ImageLoaderProvider { + ImageLoader.Builder(context = this) .allowHardware(false) .eventListener(imageLoadingTracker) .build() } - divContext = DivComposeConfiguration( + divContext = DivContext( + baseContext = this, + configuration = DivComposeConfiguration( + fontFamilyProvider = ComposeFontFamilyProvider(this) + ), debugConfiguration = DivDebugConfiguration( imageLoaderProvider = imageLoaderProvider - ), - fontFamilyProvider = ComposeFontFamilyProvider(this), - ).createContext(baseContext = this) + ) + ) intent.extras?.getString(EXTRA_DIV_ASSET_NAME)?.let { setDivData(DivAssetReader(this).read(it))