From 29347ffb4acaa0fa4b6be1fe6ee67193325a819b Mon Sep 17 00:00:00 2001 From: Mikhail Date: Thu, 10 Nov 2022 17:20:20 +0300 Subject: [PATCH] DROID-69 Tech | Feature | Add feature toggles and make logs more concise (#2699) --- app/build.gradle | 17 +++++-- .../anytype/app/DefaultFeatureToggles.kt | 24 ++++++++++ .../anytype/di/feature/DashboardDi.kt | 7 ++- .../anytypeio/anytype/di/feature/EditorDI.kt | 7 ++- .../anytypeio/anytype/di/main/DataModule.kt | 40 ++++++++-------- .../anytypeio/anytype/di/main/EventModule.kt | 18 ++++---- .../anytypeio/anytype/di/main/UtilModule.kt | 31 +++++++++++-- core-utils/build.gradle | 1 + .../core_utils/tools/FeatureToggles.kt | 15 ++++++ .../anytype/core_utils/tools/Tools.kt | 11 +++++ .../anytype/core_utils/tools/UrlValidator.kt | 3 +- dependencies.gradle | 5 +- middleware/build.gradle | 4 ++ .../anytype/middleware/UnsplashMiddleware.kt | 17 +++---- .../middleware/interactor/EventHandler.kt | 11 ++--- .../middleware/interactor/Middleware.kt | 10 ++-- .../interactor/MiddlewareProtobufLogger.kt | 46 +++++++++++++++++++ .../interactor/ProtobufConverterProvider.kt | 22 +++++++++ .../anytype/middleware/log/LogExt.kt | 13 ------ .../MiddlewareServiceImplementation.kt | 24 ++++++++-- .../com/anytypeio/anytype/MiddlewareTest.kt | 3 +- .../dashboard/HomeDashboardStateMachine.kt | 22 ++++++--- .../dashboard/HomeDashboardViewModel.kt | 7 ++- .../HomeDashboardViewModelFactory.kt | 7 ++- .../editor/ControlPanelMachine.kt | 31 +++++++------ .../editor/DocumentExternalEventReducer.kt | 5 +- .../presentation/editor/EditorViewModel.kt | 20 +++++--- .../editor/EditorViewModelFactory.kt | 7 ++- .../dashboard/DashboardTestSetup.kt | 4 +- .../dashboard/HomeDashboardViewModelTest.kt | 4 +- .../editor/ControlPanelStateReducerTest.kt | 3 +- .../editor/EditorViewModelTest.kt | 4 +- .../editor/EditorPresentationTestSetup.kt | 4 +- 33 files changed, 330 insertions(+), 117 deletions(-) create mode 100644 app/src/main/java/com/anytypeio/anytype/app/DefaultFeatureToggles.kt create mode 100644 core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/FeatureToggles.kt create mode 100644 middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/MiddlewareProtobufLogger.kt create mode 100644 middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/ProtobufConverterProvider.kt delete mode 100644 middleware/src/main/java/com/anytypeio/anytype/middleware/log/LogExt.kt diff --git a/app/build.gradle b/app/build.gradle index 2a15722cdc..7d87338bcb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,6 +13,12 @@ apikeyProperties.load(new FileInputStream(apikeyPropertiesFile)) def useReleaseKeystore = rootProject.file("scripts/release/app-release.jks").exists() +def localProperties = new Properties() +localProperties.with { + def lp = "local.properties" + if (new File(lp).exists()) it.load(new FileInputStream(lp)) +} + android { def config = rootProject.ext @@ -27,6 +33,11 @@ android { versionName getBuildVersionName() testInstrumentationRunner config.test_runner buildConfigField "boolean", "USE_NEW_WINDOW_INSET_API", "true" + buildConfigField "boolean", "LOG_FROM_MW_LIBRARY", localProperties.getProperty("LOG_FROM_MW_LIBRARY", "false") + buildConfigField "boolean", "LOG_MW_INTERACTION", localProperties.getProperty("LOG_MW_INTERACTION", "false") + buildConfigField "boolean", "LOG_DASHBOARD_REDUCER", localProperties.getProperty("LOG_DASHBOARD_REDUCER", "false") + buildConfigField "boolean", "LOG_EDITOR_VIEWMODEL_EVENTS", localProperties.getProperty("LOG_EDITOR_VIEWMODEL_EVENTS", "false") + buildConfigField "boolean", "LOG_EDITOR_CONTROL_PANEL", localProperties.getProperty("LOG_EDITOR_CONTROL_PANEL", "false") } packagingOptions { @@ -69,9 +80,9 @@ android { buildConfigField("String", "AMPLITUDE_KEY", apikeyProperties['amplitude.debug']) //signingConfig signingConfigs.debug firebaseAppDistribution { - artifactType="AAB" - groups="anytype-q&a, product-review, nightly" - serviceCredentialsFile="$rootDir/scripts/distribution/anytype-debug-service-account-key.json" + artifactType = "AAB" + groups = "anytype-q&a, product-review, nightly" + serviceCredentialsFile = "$rootDir/scripts/distribution/anytype-debug-service-account-key.json" } } } diff --git a/app/src/main/java/com/anytypeio/anytype/app/DefaultFeatureToggles.kt b/app/src/main/java/com/anytypeio/anytype/app/DefaultFeatureToggles.kt new file mode 100644 index 0000000000..103c04ef66 --- /dev/null +++ b/app/src/main/java/com/anytypeio/anytype/app/DefaultFeatureToggles.kt @@ -0,0 +1,24 @@ +package com.anytypeio.anytype.app + +import com.anytypeio.anytype.BuildConfig +import com.anytypeio.anytype.core_utils.tools.FeatureToggles +import javax.inject.Inject + +class DefaultFeatureToggles @Inject constructor() : FeatureToggles { + + override val isLogFromMiddlewareLibrary = + BuildConfig.LOG_FROM_MW_LIBRARY && BuildConfig.DEBUG + + override val isLogMiddlewareInteraction = + BuildConfig.LOG_MW_INTERACTION && BuildConfig.DEBUG + + override val isLogDashboardReducer = + BuildConfig.LOG_DASHBOARD_REDUCER && BuildConfig.DEBUG + + override val isLogEditorViewModelEvents = + BuildConfig.LOG_EDITOR_VIEWMODEL_EVENTS && BuildConfig.DEBUG + + override val isLogEditorControlPanelMachine = + BuildConfig.LOG_EDITOR_CONTROL_PANEL && BuildConfig.DEBUG + +} \ No newline at end of file diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/DashboardDi.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/DashboardDi.kt index 42a6949378..6adc6fddae 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/DashboardDi.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/DashboardDi.kt @@ -2,6 +2,7 @@ package com.anytypeio.anytype.di.feature import com.anytypeio.anytype.analytics.base.Analytics import com.anytypeio.anytype.core_utils.di.scope.PerScreen +import com.anytypeio.anytype.core_utils.tools.FeatureToggles import com.anytypeio.anytype.domain.`object`.ObjectTypesProvider import com.anytypeio.anytype.domain.auth.interactor.GetProfile import com.anytypeio.anytype.domain.auth.repo.AuthRepository @@ -76,7 +77,8 @@ object HomeDashboardModule { objectSearchSubscriptionContainer: ObjectSearchSubscriptionContainer, cancelSearchSubscription: CancelSearchSubscription, objectStore: ObjectStore, - createNewObject: CreateNewObject + createNewObject: CreateNewObject, + featureToggles: FeatureToggles ): HomeDashboardViewModelFactory = HomeDashboardViewModelFactory( getProfile = getProfile, openDashboard = openDashboard, @@ -94,7 +96,8 @@ object HomeDashboardModule { objectSearchSubscriptionContainer = objectSearchSubscriptionContainer, cancelSearchSubscription = cancelSearchSubscription, objectStore = objectStore, - createNewObject = createNewObject + createNewObject = createNewObject, + featureToggles = featureToggles ) @JvmStatic diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/EditorDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/EditorDI.kt index c50c113a9e..a323a544bc 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/EditorDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/EditorDI.kt @@ -7,6 +7,7 @@ import com.anytypeio.anytype.core_models.Id import com.anytypeio.anytype.core_models.ObjectType import com.anytypeio.anytype.core_models.Payload import com.anytypeio.anytype.core_utils.di.scope.PerScreen +import com.anytypeio.anytype.core_utils.tools.FeatureToggles import com.anytypeio.anytype.di.feature.cover.UnsplashSubComponent import com.anytypeio.anytype.di.feature.relations.RelationAddToObjectSubComponent import com.anytypeio.anytype.di.feature.relations.RelationCreateFromScratchForObjectBlockSubComponent @@ -223,7 +224,8 @@ object EditorSessionModule { setDocImageIcon: SetDocumentImageIcon, editorTemplateDelegate: EditorTemplateDelegate, createNewObject: CreateNewObject, - objectToSet: ConvertObjectToSet + objectToSet: ConvertObjectToSet, + featureToggles: FeatureToggles ): EditorViewModelFactory = EditorViewModelFactory( openPage = openPage, closeObject = closePage, @@ -255,7 +257,8 @@ object EditorSessionModule { setDocImageIcon = setDocImageIcon, editorTemplateDelegate = editorTemplateDelegate, createNewObject = createNewObject, - objectToSet = objectToSet + objectToSet = objectToSet, + featureToggles = featureToggles ) @JvmStatic diff --git a/app/src/main/java/com/anytypeio/anytype/di/main/DataModule.kt b/app/src/main/java/com/anytypeio/anytype/di/main/DataModule.kt index b1ad0bee05..cff022dc03 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/main/DataModule.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/main/DataModule.kt @@ -5,6 +5,9 @@ import android.content.SharedPreferences import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.MasterKeys import com.anytypeio.anytype.app.DefaultAppActionManager +import com.anytypeio.anytype.core_utils.tools.DefaultUrlValidator +import com.anytypeio.anytype.core_utils.tools.FeatureToggles +import com.anytypeio.anytype.core_utils.tools.UrlValidator import com.anytypeio.anytype.data.auth.config.DefaultFeaturesConfigProvider import com.anytypeio.anytype.data.auth.repo.AuthCache import com.anytypeio.anytype.data.auth.repo.AuthCacheDataStore @@ -40,18 +43,21 @@ import com.anytypeio.anytype.middleware.auth.AuthMiddleware import com.anytypeio.anytype.middleware.block.BlockMiddleware import com.anytypeio.anytype.middleware.interactor.Middleware import com.anytypeio.anytype.middleware.interactor.MiddlewareFactory +import com.anytypeio.anytype.middleware.interactor.MiddlewareProtobufLogger +import com.anytypeio.anytype.middleware.interactor.ProtobufConverterProvider import com.anytypeio.anytype.middleware.service.MiddlewareService import com.anytypeio.anytype.middleware.service.MiddlewareServiceImplementation import com.anytypeio.anytype.persistence.db.AnytypeDatabase import com.anytypeio.anytype.persistence.repo.DefaultAuthCache import com.anytypeio.anytype.persistence.repo.DefaultDebugSettingsCache import com.anytypeio.anytype.persistence.repo.DefaultUserSettingsCache +import dagger.Binds import dagger.Module import dagger.Provides import javax.inject.Named import javax.inject.Singleton -@Module +@Module(includes = [DataModule.Bindings::class]) object DataModule { @JvmStatic @@ -219,19 +225,15 @@ object DataModule { @Singleton fun provideMiddleware( service: MiddlewareService, - factory: MiddlewareFactory - ): Middleware = Middleware(service, factory) + factory: MiddlewareFactory, + logger: MiddlewareProtobufLogger + ): Middleware = Middleware(service, factory, logger) @JvmStatic @Provides @Singleton fun provideMiddlewareFactory(): MiddlewareFactory = MiddlewareFactory() - @JvmStatic - @Provides - @Singleton - fun provideMiddlewareService(): MiddlewareService = MiddlewareServiceImplementation() - @JvmStatic @Provides @Singleton @@ -282,15 +284,17 @@ object DataModule { ): UnsplashRepository = UnsplashDataRepository( remote = remote ) - - @JvmStatic - @Provides - @Singleton - fun provideUnsplashRemote( - service: MiddlewareService - ): UnsplashRemote = UnsplashMiddleware( - service = service - ) - //endregion + + @Module + interface Bindings { + + @Binds + @Singleton + fun bindUnsplashRemote(middleware: UnsplashMiddleware): UnsplashRemote + + @Binds + @Singleton + fun bindMiddlewareService(middleware: MiddlewareServiceImplementation): MiddlewareService + } } \ No newline at end of file diff --git a/app/src/main/java/com/anytypeio/anytype/di/main/EventModule.kt b/app/src/main/java/com/anytypeio/anytype/di/main/EventModule.kt index 3d056063dc..8973b9daf5 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/main/EventModule.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/main/EventModule.kt @@ -14,11 +14,12 @@ import com.anytypeio.anytype.domain.search.SubscriptionEventChannel import com.anytypeio.anytype.domain.status.ThreadStatusChannel import com.anytypeio.anytype.middleware.EventProxy import com.anytypeio.anytype.middleware.interactor.* +import dagger.Binds import dagger.Module import dagger.Provides import javax.inject.Singleton -@Module +@Module(includes = [EventModule.Bindings::class]) object EventModule { @JvmStatic @@ -88,13 +89,6 @@ object EventModule { events = proxy ) - @JvmStatic - @Provides - @Singleton - fun provideEventProxy(): EventProxy { - return EventHandler() - } - @JvmStatic @Provides @Singleton @@ -115,4 +109,12 @@ object EventModule { fun provideSubscriptionEventRemoteChannel( proxy: EventProxy ): SubscriptionEventRemoteChannel = MiddlewareSubscriptionEventChannel(events = proxy) + + @Module + interface Bindings { + + @Binds + @Singleton + fun bindEventProxy(handler: EventHandler): EventProxy + } } \ No newline at end of file diff --git a/app/src/main/java/com/anytypeio/anytype/di/main/UtilModule.kt b/app/src/main/java/com/anytypeio/anytype/di/main/UtilModule.kt index 55abf92537..be1fd1c95b 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/main/UtilModule.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/main/UtilModule.kt @@ -1,14 +1,19 @@ package com.anytypeio.anytype.di.main +import com.anytypeio.anytype.app.DefaultFeatureToggles import com.anytypeio.anytype.core_utils.tools.DefaultUrlValidator +import com.anytypeio.anytype.core_utils.tools.FeatureToggles import com.anytypeio.anytype.core_utils.tools.UrlValidator import com.anytypeio.anytype.domain.config.Gateway import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.middleware.interactor.MiddlewareProtobufLogger +import com.anytypeio.anytype.middleware.interactor.ProtobufConverterProvider +import dagger.Binds import dagger.Module import dagger.Provides import javax.inject.Singleton -@Module +@Module(includes = [UtilModule.Bindings::class]) object UtilModule { @JvmStatic @@ -16,8 +21,24 @@ object UtilModule { @Singleton fun provideUrlBuilder(gateway: Gateway): UrlBuilder = UrlBuilder(gateway) - @JvmStatic - @Provides - @Singleton - fun provideUrlValidator() : UrlValidator = DefaultUrlValidator() + + @Module + interface Bindings { + + @Binds + @Singleton + fun bindUrlValidator(applicator: DefaultUrlValidator): UrlValidator + + @Binds + @Singleton + fun bindFeatureToggles(applicator: DefaultFeatureToggles): FeatureToggles + + @Binds + @Singleton + fun bindMiddlewareProtobufLogger(logger: MiddlewareProtobufLogger.Impl): MiddlewareProtobufLogger + + @Binds + @Singleton + fun bindProtobufConverterProvider(provider: ProtobufConverterProvider.Impl): ProtobufConverterProvider + } } \ No newline at end of file diff --git a/core-utils/build.gradle b/core-utils/build.gradle index b35aa46e9c..f3b7d0a14b 100644 --- a/core-utils/build.gradle +++ b/core-utils/build.gradle @@ -39,6 +39,7 @@ dependencies { implementation applicationDependencies.kotlin implementation applicationDependencies.coroutinesAndroid implementation applicationDependencies.dagger + implementation applicationDependencies.gson implementation applicationDependencies.timber implementation applicationDependencies.crashlytics diff --git a/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/FeatureToggles.kt b/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/FeatureToggles.kt new file mode 100644 index 0000000000..a3151266bb --- /dev/null +++ b/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/FeatureToggles.kt @@ -0,0 +1,15 @@ +package com.anytypeio.anytype.core_utils.tools + +interface FeatureToggles { + + val isLogFromMiddlewareLibrary: Boolean + + val isLogMiddlewareInteraction: Boolean + + val isLogDashboardReducer: Boolean + + val isLogEditorViewModelEvents: Boolean + + val isLogEditorControlPanelMachine: Boolean + +} \ No newline at end of file diff --git a/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/Tools.kt b/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/Tools.kt index 16cd9eb480..ec394c8a68 100644 --- a/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/Tools.kt +++ b/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/Tools.kt @@ -1,6 +1,7 @@ package com.anytypeio.anytype.core_utils.tools import android.graphics.Color +import com.google.gson.GsonBuilder fun String.randomColor(): Int { var hash = 0 @@ -9,4 +10,14 @@ fun String.randomColor(): Int { } val h = (hash % 360).toFloat() return Color.HSVToColor(floatArrayOf(h, 0.5f, 0.9f)) +} + +private val gson by lazy { GsonBuilder().setPrettyPrinting().create() } + +fun Any.toPrettyString(): String { + return try { + gson.toJson(this) + } catch (e: Exception) { + this.toString() + } } \ No newline at end of file diff --git a/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/UrlValidator.kt b/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/UrlValidator.kt index 5ae8110e77..7f1dc9de73 100644 --- a/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/UrlValidator.kt +++ b/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/UrlValidator.kt @@ -1,12 +1,13 @@ package com.anytypeio.anytype.core_utils.tools import android.util.Patterns +import javax.inject.Inject interface UrlValidator { fun isValid(url: String) : Boolean } -class DefaultUrlValidator: UrlValidator { +class DefaultUrlValidator @Inject constructor(): UrlValidator { override fun isValid(url: String): Boolean { return Patterns.WEB_URL.matcher(url).matches() } diff --git a/dependencies.gradle b/dependencies.gradle index da733668e1..d62767d3a1 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -35,7 +35,8 @@ ext { javaxInject_version = '1' retrofit_version = '2.3.0' okhttp_logging_interceptor_version = '3.8.1' - gson_version = '2.8.6' + gson_version = '2.10' + gson_wire_version = '4.4.3' better_link_method_version = '2.2.0' table_view_version = '0.8.9.4' pickt_version = "2.0.2" @@ -118,6 +119,7 @@ ext { javaxAnnotation: "javax.annotation:jsr250-api:$javaxAnnotations_version", javaxInject: "javax.inject:javax.inject:$javaxInject_version", gson: "com.google.code.gson:gson:$gson_version", + gsonWire: "com.squareup.wire:wire-gson-support:$gson_wire_version", retrofit: "com.squareup.retrofit2:converter-gson:$retrofit_version", okhttpLoggingInterceptor: "com.squareup.okhttp3:logging-interceptor:$okhttp_logging_interceptor_version", timber: "com.jakewharton.timber:timber:$timber_version", @@ -177,6 +179,7 @@ ext { protobuf = [ protobufJava: "com.google.protobuf:protobuf-java:$protobuf_java_version", + protobufJavaUtil: "com.google.protobuf:protobuf-java-util:$protobuf_java_version", protoc: "com.google.protobuf:protoc:$protoc_version", wireRuntime: "com.squareup.wire:wire-runtime:$wire_version" ] diff --git a/middleware/build.gradle b/middleware/build.gradle index 16e04e2807..4ab3f66b4d 100644 --- a/middleware/build.gradle +++ b/middleware/build.gradle @@ -27,6 +27,7 @@ dependencies { implementation project(':core-models') implementation project(':protocol') implementation project(':data') + implementation project(':core-utils') def applicationDependencies = rootProject.ext.mainApplication def anytypeDependencies = rootProject.ext.anytype @@ -35,6 +36,9 @@ dependencies { implementation applicationDependencies.kotlin implementation applicationDependencies.timber implementation applicationDependencies.coroutinesAndroid + implementation applicationDependencies.gsonWire + implementation applicationDependencies.gson + implementation applicationDependencies.javaxInject implementation anytypeDependencies.middleware testImplementation project(":test:utils") diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/UnsplashMiddleware.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/UnsplashMiddleware.kt index bb39227a31..231a1c2afa 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/UnsplashMiddleware.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/UnsplashMiddleware.kt @@ -6,27 +6,28 @@ import com.anytypeio.anytype.core_models.Hash import com.anytypeio.anytype.core_models.Id import com.anytypeio.anytype.core_models.UnsplashImage import com.anytypeio.anytype.data.auth.repo.unsplash.UnsplashRemote -import com.anytypeio.anytype.middleware.log.logRequest -import com.anytypeio.anytype.middleware.log.logResponse +import com.anytypeio.anytype.middleware.interactor.MiddlewareProtobufLogger import com.anytypeio.anytype.middleware.mappers.core import com.anytypeio.anytype.middleware.service.MiddlewareService +import javax.inject.Inject -class UnsplashMiddleware( - private val service: MiddlewareService +class UnsplashMiddleware @Inject constructor( + private val service: MiddlewareService, + private val logger: MiddlewareProtobufLogger ) : UnsplashRemote { override fun search(query: String, limit: Int): List { val request = Search.Request( query = query, limit = limit - ).also { it.logRequest() } - val response = service.unsplashSearch(request = request).also { it.logResponse() } + ).also { logger.logRequest(it) } + val response = service.unsplashSearch(request = request).also { logger.logResponse(it) } return response.pictures.map { p -> p.core() } } override fun download(id: Id): Hash { - val request = Download.Request(pictureId = id).also { it.logRequest() } - val response = service.unsplashDownload(request = request).also { it.logResponse() } + val request = Download.Request(pictureId = id).also { logger.logRequest(it) } + val response = service.unsplashDownload(request = request).also { logger.logResponse(it) } return response.hash } } \ No newline at end of file diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/EventHandler.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/EventHandler.kt index 18dc9e6604..6f707f3332 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/EventHandler.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/EventHandler.kt @@ -9,11 +9,13 @@ import kotlinx.coroutines.flow.MutableSharedFlow import service.Service.setEventHandlerMobile import timber.log.Timber import java.io.IOException +import javax.inject.Inject -class EventHandler( - private val scope: CoroutineScope = GlobalScope +class EventHandler @Inject constructor( + private val logger: MiddlewareProtobufLogger ) : EventProxy { + private val scope: CoroutineScope = GlobalScope private val channel = MutableSharedFlow(0, 1) init { @@ -38,10 +40,7 @@ class EventHandler( } private fun logEvent(event: Event) { - if (BuildConfig.DEBUG) { - val message = "[" + "\n" + event::class.java.name + ":" + "\n" + event.toString() + "\n" + "]" - Timber.d(message) - } + logger.logEvent(event) } override fun flow(): Flow = channel diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt index 162acae3c8..709a048ced 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt @@ -39,11 +39,11 @@ import com.anytypeio.anytype.middleware.mappers.toMiddlewareModel import com.anytypeio.anytype.middleware.mappers.toPayload import com.anytypeio.anytype.middleware.model.CreateWalletResponse import com.anytypeio.anytype.middleware.service.MiddlewareService -import timber.log.Timber class Middleware( private val service: MiddlewareService, - private val factory: MiddlewareFactory + private val factory: MiddlewareFactory, + private val logger: MiddlewareProtobufLogger, ) { @Throws(Exception::class) @@ -1957,12 +1957,10 @@ class Middleware( } private fun logRequest(any: Any) { - val message = "===> " + any::class.java.canonicalName + ":" + "\n" + any.toString() - Timber.d(message) + logger.logRequest(any) } private fun logResponse(any: Any) { - val message = "<=== " + any::class.java.canonicalName + ":" + "\n" + any.toString() - Timber.d(message) + logger.logResponse(any) } } \ No newline at end of file diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/MiddlewareProtobufLogger.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/MiddlewareProtobufLogger.kt new file mode 100644 index 0000000000..877b3f3271 --- /dev/null +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/MiddlewareProtobufLogger.kt @@ -0,0 +1,46 @@ +package com.anytypeio.anytype.middleware.interactor + +import com.anytypeio.anytype.core_utils.tools.FeatureToggles +import com.google.gson.Gson +import timber.log.Timber +import javax.inject.Inject + +interface MiddlewareProtobufLogger { + + fun logRequest(any: Any) + + fun logResponse(any: Any) + + fun logEvent(any: Any) + + class Impl @Inject constructor( + private val protobufConverter: ProtobufConverterProvider, + private val featureToggles: FeatureToggles + ) : MiddlewareProtobufLogger { + + override fun logRequest(any: Any) { + if (featureToggles.isLogMiddlewareInteraction) { + Timber.d("request -> ${any.toLogMessage()}") + } + } + + override fun logResponse(any: Any) { + if (featureToggles.isLogMiddlewareInteraction) { + Timber.d("response -> ${any.toLogMessage()}") + } + } + + override fun logEvent(any: Any) { + if (featureToggles.isLogMiddlewareInteraction) { + Timber.d("event -> ${any.toLogMessage()}") + } + } + + private fun Any.toLogMessage(): String { + return "${this::class.java.canonicalName}:\n${ + protobufConverter.provideConverter().toJson(this) + }" + } + + } +} diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/ProtobufConverterProvider.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/ProtobufConverterProvider.kt new file mode 100644 index 0000000000..d050c0ff10 --- /dev/null +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/ProtobufConverterProvider.kt @@ -0,0 +1,22 @@ +package com.anytypeio.anytype.middleware.interactor + +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import com.squareup.wire.WireTypeAdapterFactory +import javax.inject.Inject + +interface ProtobufConverterProvider { + + fun provideConverter(): Gson + + class Impl @Inject constructor() : ProtobufConverterProvider { + private val provider = GsonBuilder() + .registerTypeAdapterFactory(WireTypeAdapterFactory()) + .setPrettyPrinting() + .create() + + override fun provideConverter(): Gson { + return provider + } + } +} \ No newline at end of file diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/log/LogExt.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/log/LogExt.kt deleted file mode 100644 index 49ee16061e..0000000000 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/log/LogExt.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.anytypeio.anytype.middleware.log - -import timber.log.Timber - -fun Any.logResponse() { - val message = "===> " + this::class.java.canonicalName + ":" + "\n" + this.toString() - Timber.d(message) -} - -fun Any.logRequest() { - val message = "<=== " + this::class.java.canonicalName + ":" + "\n" + this.toString() - Timber.d(message) -} diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareServiceImplementation.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareServiceImplementation.kt index c69227278c..e83c189494 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareServiceImplementation.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareServiceImplementation.kt @@ -3,12 +3,22 @@ package com.anytypeio.anytype.middleware.service import anytype.Rpc import com.anytypeio.anytype.core_models.exceptions.AccountIsDeletedException import com.anytypeio.anytype.core_models.exceptions.CreateAccountException +import com.anytypeio.anytype.core_utils.tools.FeatureToggles import com.anytypeio.anytype.data.auth.exception.BackwardCompatilityNotSupportedException import com.anytypeio.anytype.data.auth.exception.NotFoundObjectException import com.anytypeio.anytype.data.auth.exception.UndoRedoExhaustedException import service.Service +import javax.inject.Inject -class MiddlewareServiceImplementation : MiddlewareService { +class MiddlewareServiceImplementation @Inject constructor( + featureToggles: FeatureToggles +) : MiddlewareService { + + init { + if (!featureToggles.isLogFromMiddlewareLibrary) { + Service.setEnv("ANYTYPE_LOG_LEVEL", "*=fatal;anytype*=error") + } + } override fun accountCreate(request: Rpc.Account.Create.Request): Rpc.Account.Create.Response { val encoded = Service.accountCreate(Rpc.Account.Create.Request.ADAPTER.encode(request)) @@ -655,7 +665,8 @@ class MiddlewareServiceImplementation : MiddlewareService { } override fun objectCreateBookmark(request: Rpc.Object.CreateBookmark.Request): Rpc.Object.CreateBookmark.Response { - val encoded = Service.objectCreateBookmark(Rpc.Object.CreateBookmark.Request.ADAPTER.encode(request)) + val encoded = + Service.objectCreateBookmark(Rpc.Object.CreateBookmark.Request.ADAPTER.encode(request)) val response = Rpc.Object.CreateBookmark.Response.ADAPTER.decode(encoded) val error = response.error if (error != null && error.code != Rpc.Object.CreateBookmark.Response.Error.Code.NULL) { @@ -666,7 +677,8 @@ class MiddlewareServiceImplementation : MiddlewareService { } override fun objectBookmarkFetch(request: Rpc.Object.BookmarkFetch.Request): Rpc.Object.BookmarkFetch.Response { - val encoded = Service.objectBookmarkFetch(Rpc.Object.BookmarkFetch.Request.ADAPTER.encode(request)) + val encoded = + Service.objectBookmarkFetch(Rpc.Object.BookmarkFetch.Request.ADAPTER.encode(request)) val response = Rpc.Object.BookmarkFetch.Response.ADAPTER.decode(encoded) val error = response.error if (error != null && error.code != Rpc.Object.BookmarkFetch.Response.Error.Code.NULL) { @@ -1119,7 +1131,11 @@ class MiddlewareServiceImplementation : MiddlewareService { override fun blockDataViewSetSource(request: Rpc.BlockDataview.SetSource.Request): Rpc.BlockDataview.SetSource.Response { val encoded = - Service.blockDataviewSetSource(Rpc.BlockDataview.SetSource.Request.ADAPTER.encode(request)) + Service.blockDataviewSetSource( + Rpc.BlockDataview.SetSource.Request.ADAPTER.encode( + request + ) + ) val response = Rpc.BlockDataview.SetSource.Response.ADAPTER.decode(encoded) val error = response.error if (error != null && error.code != Rpc.BlockDataview.SetSource.Response.Error.Code.NULL) { diff --git a/middleware/src/test/java/com/anytypeio/anytype/MiddlewareTest.kt b/middleware/src/test/java/com/anytypeio/anytype/MiddlewareTest.kt index f59a66b0df..163d008037 100644 --- a/middleware/src/test/java/com/anytypeio/anytype/MiddlewareTest.kt +++ b/middleware/src/test/java/com/anytypeio/anytype/MiddlewareTest.kt @@ -17,6 +17,7 @@ import org.mockito.Mock import org.mockito.MockitoAnnotations import org.mockito.kotlin.any import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock import org.mockito.kotlin.stub import org.mockito.kotlin.times import org.mockito.kotlin.verify @@ -42,7 +43,7 @@ class MiddlewareTest { @Before fun setup() { MockitoAnnotations.openMocks(this) - middleware = Middleware(service, factory) + middleware = Middleware(service, factory, mock()) } @Test diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardStateMachine.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardStateMachine.kt index 75929a1131..2136670066 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardStateMachine.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardStateMachine.kt @@ -7,6 +7,8 @@ import com.anytypeio.anytype.core_models.ext.amend import com.anytypeio.anytype.core_models.ext.getChildrenIdsList import com.anytypeio.anytype.core_models.ext.set import com.anytypeio.anytype.core_models.ext.unset +import com.anytypeio.anytype.core_utils.tools.FeatureToggles +import com.anytypeio.anytype.core_utils.tools.toPrettyString import com.anytypeio.anytype.domain.misc.UrlBuilder import com.anytypeio.anytype.presentation.common.StateReducer import com.anytypeio.anytype.presentation.dashboard.HomeDashboardStateMachine.Event @@ -34,7 +36,7 @@ sealed class HomeDashboardStateMachine { class Interactor( private val scope: CoroutineScope, - private val reducer: Reducer = Reducer(), + private val reducer: Reducer, private val channel: Channel> = Channel(), private val events: Flow> = channel.consumeAsFlow() ) { @@ -116,13 +118,19 @@ sealed class HomeDashboardStateMachine { object OnFinishedCreatingPage : Event() } - class Reducer : StateReducer> { + class Reducer(private val featureToggles: FeatureToggles) : StateReducer> { override val function: suspend (State, List) -> State get() = { state, events -> - Timber.d("REDUCE, STATE:$state, EVENT:$events") + if (featureToggles.isLogDashboardReducer) { + Timber.d("REDUCE, STATE:$state, EVENT:${events.toPrettyString()}") + } + val update = reduce(state, events) - Timber.d("REDUCE, UPDATED STATE:$update") + + if (featureToggles.isLogDashboardReducer) { + Timber.d("REDUCE, UPDATED STATE:${update.toPrettyString()}") + } update } @@ -148,9 +156,9 @@ sealed class HomeDashboardStateMachine { is Event.OnShowDashboard -> { val new = event.blocks.toDashboardViews( - details = event.details, - builder = event.builder, - objectTypes = event.objectTypes + details = event.details, + builder = event.builder, + objectTypes = event.objectTypes ) val childrenIdsList = event.blocks.getChildrenIdsList(parent = event.context) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardViewModel.kt index 567994a11f..27eb3f4ebb 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardViewModel.kt @@ -22,6 +22,7 @@ import com.anytypeio.anytype.core_models.Position import com.anytypeio.anytype.core_models.Relations import com.anytypeio.anytype.core_utils.common.EventWrapper import com.anytypeio.anytype.core_utils.ext.withLatestFrom +import com.anytypeio.anytype.core_utils.tools.FeatureToggles import com.anytypeio.anytype.core_utils.ui.ViewState import com.anytypeio.anytype.core_utils.ui.ViewStateViewModel import com.anytypeio.anytype.domain.auth.interactor.GetProfile @@ -41,6 +42,7 @@ import com.anytypeio.anytype.domain.search.CancelSearchSubscription import com.anytypeio.anytype.domain.search.ObjectSearchSubscriptionContainer import com.anytypeio.anytype.presentation.BuildConfig import com.anytypeio.anytype.presentation.dashboard.HomeDashboardStateMachine.Interactor +import com.anytypeio.anytype.presentation.dashboard.HomeDashboardStateMachine.Reducer import com.anytypeio.anytype.presentation.dashboard.HomeDashboardStateMachine.State import com.anytypeio.anytype.presentation.extension.sendAnalyticsRemoveObjects import com.anytypeio.anytype.presentation.extension.sendAnalyticsRestoreFromBin @@ -84,7 +86,8 @@ class HomeDashboardViewModel( private val objectSearchSubscriptionContainer: ObjectSearchSubscriptionContainer, private val cancelSearchSubscription: CancelSearchSubscription, private val objectStore: ObjectStore, - private val createNewObject: CreateNewObject + private val createNewObject: CreateNewObject, + featureToggles: FeatureToggles ) : ViewStateViewModel(), HomeDashboardEventConverter by eventConverter, SupportNavigation> { @@ -93,7 +96,7 @@ class HomeDashboardViewModel( val toasts = MutableSharedFlow() - private val machine = Interactor(scope = viewModelScope) + private val machine = Interactor(scope = viewModelScope, reducer = Reducer(featureToggles)) private val movementChannel = Channel() private val movementChanges = movementChannel.consumeAsFlow() diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardViewModelFactory.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardViewModelFactory.kt index 61a980568f..6baaa843c7 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardViewModelFactory.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardViewModelFactory.kt @@ -3,6 +3,7 @@ package com.anytypeio.anytype.presentation.dashboard import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import com.anytypeio.anytype.analytics.base.Analytics +import com.anytypeio.anytype.core_utils.tools.FeatureToggles import com.anytypeio.anytype.domain.auth.interactor.GetProfile import com.anytypeio.anytype.domain.block.interactor.Move import com.anytypeio.anytype.domain.config.GetConfig @@ -36,7 +37,8 @@ class HomeDashboardViewModelFactory( private val objectSearchSubscriptionContainer: ObjectSearchSubscriptionContainer, private val cancelSearchSubscription: CancelSearchSubscription, private val objectStore: ObjectStore, - private val createNewObject: CreateNewObject + private val createNewObject: CreateNewObject, + private val featureToggles: FeatureToggles ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") @@ -58,7 +60,8 @@ class HomeDashboardViewModelFactory( objectSearchSubscriptionContainer = objectSearchSubscriptionContainer, cancelSearchSubscription = cancelSearchSubscription, objectStore = objectStore, - createNewObject = createNewObject + createNewObject = createNewObject, + featureToggles = featureToggles ) as T } } \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/ControlPanelMachine.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/ControlPanelMachine.kt index c50769b597..56e86cefe9 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/ControlPanelMachine.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/ControlPanelMachine.kt @@ -4,6 +4,8 @@ import com.anytypeio.anytype.core_models.Block import com.anytypeio.anytype.core_models.Block.Content.Text.Style import com.anytypeio.anytype.core_models.Id import com.anytypeio.anytype.core_models.TextBlock +import com.anytypeio.anytype.core_utils.tools.FeatureToggles +import com.anytypeio.anytype.core_utils.tools.toPrettyString import com.anytypeio.anytype.presentation.common.StateReducer import com.anytypeio.anytype.presentation.editor.ControlPanelMachine.Event import com.anytypeio.anytype.presentation.editor.ControlPanelMachine.Interactor @@ -42,10 +44,10 @@ sealed class ControlPanelMachine { * @property scope coroutine scope (state machine runs inside this scope) */ class Interactor( - private val scope: CoroutineScope + private val scope: CoroutineScope, + private val reducer: Reducer ) : ControlPanelMachine() { - private val reducer: Reducer = Reducer() val channel: Channel = Channel() private val events: Flow = channel.consumeAsFlow() @@ -232,7 +234,8 @@ sealed class ControlPanelMachine { /** * Concrete reducer implementation that holds all the logic related to control panels. */ - class Reducer : StateReducer { + class Reducer(private val featureToggles: FeatureToggles) : + StateReducer { override val function: suspend (ControlPanelState, Event) -> ControlPanelState get() = { state, event -> @@ -938,19 +941,21 @@ sealed class ControlPanelMachine { } private fun logState(text: String, state: ControlPanelState) { - Timber.i( - "REDUCER, $text STATE:${ - state - }" - ) + if (featureToggles.isLogEditorControlPanelMachine) { + Timber.i( + "REDUCER, $text STATE:${state.toPrettyString()}" + ) + } } private fun logEvent(event: Event) { - Timber.i( - "REDUCER, EVENT:${ - event::class.qualifiedName?.substringAfter("Event.") - }" - ) + if (featureToggles.isLogEditorControlPanelMachine) { + Timber.i( + "REDUCER, EVENT:${ + event::class.qualifiedName?.substringAfter("Event.") + }" + ) + } } } } \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/DocumentExternalEventReducer.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/DocumentExternalEventReducer.kt index 9198217fd8..9663ea3993 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/DocumentExternalEventReducer.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/DocumentExternalEventReducer.kt @@ -6,6 +6,7 @@ import com.anytypeio.anytype.core_models.Id import com.anytypeio.anytype.core_models.Relations import com.anytypeio.anytype.core_models.ext.content import com.anytypeio.anytype.core_utils.ext.replace +import com.anytypeio.anytype.core_utils.tools.toPrettyString import com.anytypeio.anytype.presentation.common.StateReducer import timber.log.Timber @@ -142,7 +143,9 @@ class DocumentExternalEventReducer : StateReducer, Event> { target = { block -> block.id == event.id } ) - else -> state.also { Timber.d("Ignoring event: $event") } + else -> state.also { + Timber.d("Ignoring event: ${event::class.java.canonicalName}:\n${event.toPrettyString()}") + } } } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt index 487cf90665..ddca3a35d3 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt @@ -88,6 +88,8 @@ import com.anytypeio.anytype.presentation.editor.editor.Orchestrator import com.anytypeio.anytype.presentation.editor.editor.Proxy import com.anytypeio.anytype.presentation.editor.editor.SideEffect import com.anytypeio.anytype.core_models.ThemeColor +import com.anytypeio.anytype.core_utils.tools.FeatureToggles +import com.anytypeio.anytype.core_utils.tools.toPrettyString import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet import com.anytypeio.anytype.presentation.editor.editor.ViewState import com.anytypeio.anytype.presentation.editor.editor.actions.ActionItemType @@ -249,7 +251,8 @@ class EditorViewModel( private val setDocImageIcon: SetDocumentImageIcon, private val templateDelegate: EditorTemplateDelegate, private val createNewObject: CreateNewObject, - private val objectToSet: ConvertObjectToSet + private val objectToSet: ConvertObjectToSet, + private val featureToggles: FeatureToggles ) : ViewStateViewModel(), PickerListener, SupportNavigation>, @@ -295,7 +298,10 @@ class EditorViewModel( val footers = MutableStateFlow(EditorFooter.None) - private val controlPanelInteractor = Interactor(viewModelScope) + private val controlPanelInteractor = Interactor( + viewModelScope, + reducer = ControlPanelMachine.Reducer(featureToggles) + ) val controlPanelViewState = MutableLiveData() /** @@ -496,9 +502,9 @@ class EditorViewModel( } private suspend fun processEvents(events: List): List { - if (BuildConfig.DEBUG) { - Timber.d("Blocks before handling events: $blocks") - Timber.d("Events: $events") + if (featureToggles.isLogEditorViewModelEvents) { + Timber.d("Blocks before handling events: ${blocks.toPrettyString()}") + Timber.d("Events: ${events.toPrettyString()}") } events.forEach { event -> when (event) { @@ -522,8 +528,8 @@ class EditorViewModel( } orchestrator.stores.document.update(reduce(blocks, event)) } - if (BuildConfig.DEBUG) { - Timber.d("Blocks after handling events: $blocks") + if (featureToggles.isLogEditorViewModelEvents) { + Timber.d("Blocks after handling events: ${blocks.toPrettyString()}") } return events.flags(context) } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModelFactory.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModelFactory.kt index 229b43489e..4740a05e84 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModelFactory.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModelFactory.kt @@ -6,6 +6,7 @@ import com.anytypeio.anytype.analytics.base.Analytics import com.anytypeio.anytype.core_models.Block import com.anytypeio.anytype.core_models.Event import com.anytypeio.anytype.core_models.Payload +import com.anytypeio.anytype.core_utils.tools.FeatureToggles import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet import com.anytypeio.anytype.domain.`object`.ObjectTypesProvider import com.anytypeio.anytype.domain.`object`.UpdateDetail @@ -69,7 +70,8 @@ open class EditorViewModelFactory( private val setDocImageIcon: SetDocumentImageIcon, private val editorTemplateDelegate: EditorTemplateDelegate, private val createNewObject: CreateNewObject, - private val objectToSet: ConvertObjectToSet + private val objectToSet: ConvertObjectToSet, + private val featureToggles: FeatureToggles ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") @@ -105,7 +107,8 @@ open class EditorViewModelFactory( setDocImageIcon = setDocImageIcon, templateDelegate = editorTemplateDelegate, createNewObject = createNewObject, - objectToSet = objectToSet + objectToSet = objectToSet, + featureToggles = featureToggles ) as T } } \ No newline at end of file diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/dashboard/DashboardTestSetup.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/dashboard/DashboardTestSetup.kt index 252d3ddb35..2f59577365 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/dashboard/DashboardTestSetup.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/dashboard/DashboardTestSetup.kt @@ -40,6 +40,7 @@ import org.mockito.Mock import org.mockito.kotlin.any import org.mockito.kotlin.doAnswer import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock import org.mockito.kotlin.stub open class DashboardTestSetup { @@ -147,7 +148,8 @@ open class DashboardTestSetup { main = coroutineTestRule.testDispatcher ) ), - createNewObject = createNewObject + createNewObject = createNewObject, + featureToggles = mock() ) } diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardViewModelTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardViewModelTest.kt index c894165c95..3f665977dd 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardViewModelTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/dashboard/HomeDashboardViewModelTest.kt @@ -51,6 +51,7 @@ import org.mockito.kotlin.atLeast import org.mockito.kotlin.doAnswer import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq +import org.mockito.kotlin.mock import org.mockito.kotlin.stub import org.mockito.kotlin.times import org.mockito.kotlin.verify @@ -152,7 +153,8 @@ class HomeDashboardViewModelTest { cancelSearchSubscription = cancelSearchSubscription, objectStore = objectStore, objectSearchSubscriptionContainer = objectSearchSubscriptionContainer, - createNewObject = createNewObject + createNewObject = createNewObject, + featureToggles = mock() ) } diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/ControlPanelStateReducerTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/ControlPanelStateReducerTest.kt index e6945df2ba..f4b72eb2bc 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/ControlPanelStateReducerTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/ControlPanelStateReducerTest.kt @@ -16,6 +16,7 @@ import org.junit.Rule import org.junit.Test import org.mockito.Mock import org.mockito.MockitoAnnotations +import org.mockito.kotlin.mock import kotlin.test.assertEquals @@ -28,7 +29,7 @@ class ControlPanelStateReducerTest { lateinit var gateway: Gateway lateinit var urlBuilder: UrlBuilder - private val reducer = ControlPanelMachine.Reducer() + private val reducer = ControlPanelMachine.Reducer(mock()) val paragraph = Block( id = MockDataFactory.randomUuid(), diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/EditorViewModelTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/EditorViewModelTest.kt index b748015e5f..f03701a005 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/EditorViewModelTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/EditorViewModelTest.kt @@ -137,6 +137,7 @@ import org.mockito.kotlin.doAnswer import org.mockito.kotlin.doReturn import org.mockito.kotlin.doThrow import org.mockito.kotlin.eq +import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.stub import org.mockito.kotlin.times @@ -4018,7 +4019,8 @@ open class EditorViewModelTest { setDocImageIcon = setDocImageIcon, templateDelegate = editorTemplateDelegate, createNewObject = createNewObject, - objectToSet = objectToSet + objectToSet = objectToSet, + featureToggles = mock() ) } diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorPresentationTestSetup.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorPresentationTestSetup.kt index e164b72e80..d761812d5a 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorPresentationTestSetup.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorPresentationTestSetup.kt @@ -93,6 +93,7 @@ import org.mockito.Mock import org.mockito.kotlin.any import org.mockito.kotlin.doAnswer import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock import org.mockito.kotlin.stub open class EditorPresentationTestSetup { @@ -376,7 +377,8 @@ open class EditorPresentationTestSetup { setDocImageIcon = setDocImageIcon, templateDelegate = editorTemplateDelegate, createNewObject = createNewObject, - objectToSet = objectToSet + objectToSet = objectToSet, + featureToggles = mock() ) }