mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-1305 App | Enhancement | About app screen (#3210)
* DROID-1305 about app di * DROID-1305 sentry crash report implementation * DROID-1305 sentry, send analytics id * DROID-1305 build provider, debug state * DROID-1305 about app screen, redesign + show analytics id * DROID-1305 string resources * DROID-1305 sentry module deps * DROID-1305 fix tests * DROID-1305 moving crashReporter to crash module
This commit is contained in:
parent
1ea667a6b1
commit
425598a6b6
22 changed files with 198 additions and 74 deletions
|
@ -14,6 +14,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
|||
import com.anytypeio.anytype.domain.config.ConfigStorage
|
||||
import com.anytypeio.anytype.domain.config.FeaturesConfigProvider
|
||||
import com.anytypeio.anytype.domain.device.PathProvider
|
||||
import com.anytypeio.anytype.CrashReporter
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.workspace.WorkspaceManager
|
||||
|
@ -79,6 +80,9 @@ class SetupSelectedAccountTest {
|
|||
@Mock
|
||||
private lateinit var objectTypesSubscriptionManager: ObjectTypesSubscriptionManager
|
||||
|
||||
@Mock
|
||||
private lateinit var crashReporter: CrashReporter
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.openMocks(this)
|
||||
|
@ -94,7 +98,8 @@ class SetupSelectedAccountTest {
|
|||
pathProvider = pathProvider,
|
||||
analytics = analytics,
|
||||
objectTypesSubscriptionManager = objectTypesSubscriptionManager,
|
||||
relationsSubscriptionManager = relationsSubscriptionManager
|
||||
relationsSubscriptionManager = relationsSubscriptionManager,
|
||||
crashReporter = crashReporter
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.anytypeio.anytype.app
|
|||
import android.app.Application
|
||||
import com.amplitude.api.Amplitude
|
||||
import com.anytypeio.anytype.BuildConfig
|
||||
import com.anytypeio.anytype.SentryCrashReporter
|
||||
import com.anytypeio.anytype.CrashReporter
|
||||
import com.anytypeio.anytype.analytics.tracker.AmplitudeTracker
|
||||
import com.anytypeio.anytype.di.common.ComponentDependenciesProvider
|
||||
import com.anytypeio.anytype.di.common.ComponentManager
|
||||
|
@ -28,7 +28,7 @@ class AndroidApplication : Application(), HasComponentDependencies {
|
|||
lateinit var discoveryManager: MDNSProvider
|
||||
|
||||
@Inject
|
||||
lateinit var sentryCrashReporter: SentryCrashReporter
|
||||
lateinit var crashReporter: CrashReporter
|
||||
|
||||
@Inject
|
||||
override lateinit var dependencies: ComponentDependenciesProvider
|
||||
|
@ -50,7 +50,7 @@ class AndroidApplication : Application(), HasComponentDependencies {
|
|||
main.inject(this)
|
||||
setupAnalytics()
|
||||
setupTimber()
|
||||
setupSentry()
|
||||
setupCrashReporter()
|
||||
setupLocalNetworkAddressHandler()
|
||||
}
|
||||
|
||||
|
@ -58,10 +58,8 @@ class AndroidApplication : Application(), HasComponentDependencies {
|
|||
if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
|
||||
}
|
||||
|
||||
private fun setupSentry() {
|
||||
sentryCrashReporter.init(
|
||||
withTimber = !BuildConfig.DEBUG
|
||||
)
|
||||
private fun setupCrashReporter() {
|
||||
crashReporter.init()
|
||||
}
|
||||
|
||||
private fun setupAnalytics() {
|
||||
|
|
|
@ -81,7 +81,7 @@ import com.anytypeio.anytype.di.feature.sets.PickConditionModule
|
|||
import com.anytypeio.anytype.di.feature.sets.SelectFilterRelationModule
|
||||
import com.anytypeio.anytype.di.feature.sets.viewer.ViewerCardSizeSelectModule
|
||||
import com.anytypeio.anytype.di.feature.sets.viewer.ViewerImagePreviewSelectModule
|
||||
import com.anytypeio.anytype.di.feature.settings.AboutAppModule
|
||||
import com.anytypeio.anytype.di.feature.settings.DaggerAboutAppComponent
|
||||
import com.anytypeio.anytype.di.feature.settings.ProfileModule
|
||||
import com.anytypeio.anytype.di.feature.settings.DaggerAppearanceComponent
|
||||
import com.anytypeio.anytype.di.feature.settings.DaggerFilesStorageComponent
|
||||
|
@ -812,7 +812,7 @@ class ComponentManager(
|
|||
// Settings
|
||||
|
||||
val aboutAppComponent = Component {
|
||||
main.aboutAppComponent().module(AboutAppModule).build()
|
||||
DaggerAboutAppComponent.factory().create(findComponentDependencies())
|
||||
}
|
||||
|
||||
val profileComponent = Component {
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.anytypeio.anytype.domain.auth.repo.AuthRepository
|
|||
import com.anytypeio.anytype.domain.config.ConfigStorage
|
||||
import com.anytypeio.anytype.domain.config.FeaturesConfigProvider
|
||||
import com.anytypeio.anytype.domain.device.PathProvider
|
||||
import com.anytypeio.anytype.CrashReporter
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.workspace.WorkspaceManager
|
||||
|
@ -254,14 +255,16 @@ object SetupSelectedAccountModule {
|
|||
pathProvider: PathProvider,
|
||||
analytics: Analytics,
|
||||
relationsSubscriptionManager: RelationsSubscriptionManager,
|
||||
objectTypesSubscriptionManager: ObjectTypesSubscriptionManager
|
||||
objectTypesSubscriptionManager: ObjectTypesSubscriptionManager,
|
||||
crashReporter: CrashReporter
|
||||
): SetupSelectedAccountViewModelFactory {
|
||||
return SetupSelectedAccountViewModelFactory(
|
||||
selectAccount = selectAccount,
|
||||
pathProvider = pathProvider,
|
||||
analytics = analytics,
|
||||
relationsSubscriptionManager = relationsSubscriptionManager,
|
||||
objectTypesSubscriptionManager = objectTypesSubscriptionManager
|
||||
objectTypesSubscriptionManager = objectTypesSubscriptionManager,
|
||||
crashReporter = crashReporter
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
|||
import com.anytypeio.anytype.domain.device.PathProvider
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultEditorType
|
||||
import com.anytypeio.anytype.CrashReporter
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
|
@ -171,4 +172,5 @@ interface SplashDependencies : ComponentDependencies {
|
|||
fun configStorage(): ConfigStorage
|
||||
fun userSettingsRepository(): UserSettingsRepository
|
||||
fun dispatchers(): AppCoroutineDispatchers
|
||||
fun crashReporter(): CrashReporter
|
||||
}
|
|
@ -1,24 +1,30 @@
|
|||
package com.anytypeio.anytype.di.feature.settings
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
|
||||
import com.anytypeio.anytype.di.common.ComponentDependencies
|
||||
import com.anytypeio.anytype.domain.auth.interactor.GetAccount
|
||||
import com.anytypeio.anytype.domain.auth.interactor.GetLibraryVersion
|
||||
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
|
||||
import com.anytypeio.anytype.domain.config.ConfigStorage
|
||||
import com.anytypeio.anytype.ui.settings.AboutAppFragment
|
||||
import com.anytypeio.anytype.ui_settings.about.AboutAppViewModel
|
||||
import dagger.Binds
|
||||
import dagger.Component
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.Subcomponent
|
||||
import javax.inject.Scope
|
||||
|
||||
@Subcomponent(modules = [AboutAppModule::class])
|
||||
@PerScreen
|
||||
interface AboutAppSubComponent {
|
||||
@Component(
|
||||
modules = [AboutAppModule::class],
|
||||
dependencies = [AboutAppDependencies::class]
|
||||
)
|
||||
@AboutAppScope
|
||||
interface AboutAppComponent {
|
||||
|
||||
@Subcomponent.Builder
|
||||
interface Builder {
|
||||
fun module(module: AboutAppModule): Builder
|
||||
fun build(): AboutAppSubComponent
|
||||
@Component.Factory
|
||||
interface Factory {
|
||||
fun create(dependencies: AboutAppDependencies): AboutAppComponent
|
||||
}
|
||||
|
||||
fun inject(fragment: AboutAppFragment)
|
||||
|
@ -29,28 +35,35 @@ object AboutAppModule {
|
|||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideViewModelFactory(
|
||||
getAccount: GetAccount,
|
||||
getLibraryVersion: GetLibraryVersion,
|
||||
analytics: Analytics
|
||||
): AboutAppViewModel.Factory = AboutAppViewModel.Factory(
|
||||
getAccount = getAccount,
|
||||
getLibraryVersion = getLibraryVersion,
|
||||
analytics = analytics
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
@AboutAppScope
|
||||
fun provideGetAccountUseCase(
|
||||
repo: AuthRepository
|
||||
): GetAccount = GetAccount(repo = repo)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
@AboutAppScope
|
||||
fun provideGetVersion(
|
||||
repo: AuthRepository
|
||||
): GetLibraryVersion = GetLibraryVersion(repo)
|
||||
}
|
||||
|
||||
@Module
|
||||
interface Declarations {
|
||||
|
||||
@AboutAppScope
|
||||
@Binds
|
||||
fun bindViewModelFactory(
|
||||
factory: AboutAppViewModel.Factory
|
||||
): ViewModelProvider.Factory
|
||||
}
|
||||
}
|
||||
|
||||
interface AboutAppDependencies : ComponentDependencies {
|
||||
fun authRepo(): AuthRepository
|
||||
fun configStorage(): ConfigStorage
|
||||
fun analytics(): Analytics
|
||||
}
|
||||
|
||||
@Scope
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class AboutAppScope
|
|
@ -1,8 +1,10 @@
|
|||
package com.anytypeio.anytype.di.main
|
||||
|
||||
import android.content.Context
|
||||
import com.anytypeio.anytype.CrashReporter
|
||||
import com.anytypeio.anytype.SentryCrashReporter
|
||||
import com.anytypeio.anytype.core_utils.tools.AppInfo
|
||||
import com.anytypeio.anytype.device.BuildProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import javax.inject.Singleton
|
||||
|
@ -15,7 +17,11 @@ object CrashReportingModule {
|
|||
@Singleton
|
||||
fun provideCrashReporter(
|
||||
context: Context,
|
||||
appInfo: AppInfo
|
||||
): SentryCrashReporter = SentryCrashReporter(context, appInfo)
|
||||
|
||||
appInfo: AppInfo,
|
||||
buildProvider: BuildProvider
|
||||
): CrashReporter = SentryCrashReporter(
|
||||
context = context,
|
||||
appInfo = appInfo,
|
||||
withTimber = !buildProvider.isDebug()
|
||||
)
|
||||
}
|
|
@ -27,7 +27,7 @@ import com.anytypeio.anytype.di.feature.onboarding.OnboardingMnemonicDependencie
|
|||
import com.anytypeio.anytype.di.feature.onboarding.OnboardingSoulCreationDependencies
|
||||
import com.anytypeio.anytype.di.feature.relations.RelationCreateFromLibraryDependencies
|
||||
import com.anytypeio.anytype.di.feature.relations.RelationEditDependencies
|
||||
import com.anytypeio.anytype.di.feature.settings.AboutAppSubComponent
|
||||
import com.anytypeio.anytype.di.feature.settings.AboutAppDependencies
|
||||
import com.anytypeio.anytype.di.feature.settings.ProfileSubComponent
|
||||
import com.anytypeio.anytype.di.feature.settings.AppearanceDependencies
|
||||
import com.anytypeio.anytype.di.feature.settings.FilesStorageDependencies
|
||||
|
@ -84,7 +84,8 @@ interface MainComponent :
|
|||
OnboardingAuthDependencies,
|
||||
OnboardingInviteCodeDependencies,
|
||||
OnboardingMnemonicDependencies,
|
||||
OnboardingSoulCreationDependencies {
|
||||
OnboardingSoulCreationDependencies,
|
||||
AboutAppDependencies {
|
||||
|
||||
fun inject(app: AndroidApplication)
|
||||
|
||||
|
@ -108,7 +109,6 @@ interface MainComponent :
|
|||
|
||||
//region Settings
|
||||
|
||||
fun aboutAppComponent(): AboutAppSubComponent.Builder
|
||||
fun profileComponent(): ProfileSubComponent.Builder
|
||||
fun debugSettingsBuilder(): DebugSettingsSubComponent.Builder
|
||||
fun keychainPhraseComponentBuilder(): KeychainPhraseSubComponent.Builder
|
||||
|
@ -212,4 +212,8 @@ private abstract class ComponentDependenciesModule private constructor() {
|
|||
@ComponentDependenciesKey(OnboardingSoulCreationDependencies::class)
|
||||
abstract fun provideOnboardingSoulCreationDependencies(component: MainComponent): ComponentDependencies
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ComponentDependenciesKey(AboutAppDependencies::class)
|
||||
abstract fun provideAboutAppDependencies(component: MainComponent): ComponentDependencies
|
||||
}
|
|
@ -16,7 +16,6 @@ import androidx.compose.runtime.collectAsState
|
|||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.capitalize
|
||||
import androidx.compose.ui.text.font.Font
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
|
@ -54,7 +53,8 @@ class AboutAppFragment : BaseBottomSheetComposeFragment() {
|
|||
version = getVersionText(),
|
||||
buildNumber = getBuildNumber(),
|
||||
libraryVersion = vm.libraryVersion.collectAsState().value,
|
||||
anytypeId = vm.userId.collectAsState().value,
|
||||
accountId = vm.accountId.collectAsState().value,
|
||||
analyticsId = vm.analyticsId.collectAsState().value,
|
||||
onMetaClicked = { copyMetaToClipboard() }
|
||||
) {
|
||||
vm.onExternalLinkClicked(it)
|
||||
|
@ -115,7 +115,8 @@ class AboutAppFragment : BaseBottomSheetComposeFragment() {
|
|||
getVersionText(),
|
||||
getBuildNumber(),
|
||||
vm.libraryVersion.value,
|
||||
vm.userId.value
|
||||
vm.accountId.value,
|
||||
vm.analyticsId.value
|
||||
)
|
||||
)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package com.anytypeio.anytype
|
||||
|
||||
interface CrashReporter {
|
||||
fun init()
|
||||
fun setUser(userId: String)
|
||||
}
|
|
@ -2,18 +2,22 @@ package com.anytypeio.anytype
|
|||
|
||||
import android.content.Context
|
||||
import com.anytypeio.anytype.core_utils.tools.AppInfo
|
||||
import io.sentry.Sentry
|
||||
import io.sentry.SentryLevel
|
||||
import io.sentry.android.core.SentryAndroid
|
||||
import io.sentry.android.core.SentryAndroidOptions
|
||||
import io.sentry.android.timber.SentryTimberIntegration
|
||||
import io.sentry.protocol.User
|
||||
import java.lang.Exception
|
||||
import timber.log.Timber
|
||||
|
||||
class SentryCrashReporter(
|
||||
private val context: Context,
|
||||
private val appInfo: AppInfo,
|
||||
) {
|
||||
fun init(
|
||||
withTimber: Boolean
|
||||
) {
|
||||
private val withTimber: Boolean
|
||||
) : CrashReporter {
|
||||
|
||||
override fun init() {
|
||||
SentryAndroid.init(context) { options: SentryAndroidOptions ->
|
||||
with(options) {
|
||||
release = appInfo.versionName
|
||||
|
@ -29,4 +33,15 @@ class SentryCrashReporter(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUser(userId: String) {
|
||||
try {
|
||||
val user = User().apply {
|
||||
id = userId
|
||||
}
|
||||
Sentry.setUser(user)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Sentry set user error")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ dependencies {
|
|||
implementation project(':library-emojifier')
|
||||
implementation project(':analytics')
|
||||
implementation project(':core-models')
|
||||
implementation project(':crash-reporting')
|
||||
|
||||
implementation libs.kotlin
|
||||
implementation libs.coroutinesAndroid
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package com.anytypeio.anytype.device
|
||||
|
||||
import android.os.Build
|
||||
import com.anytypeio.anytype.presentation.BuildConfig
|
||||
|
||||
interface BuildProvider {
|
||||
fun getManufacturer(): String
|
||||
fun getModel(): String
|
||||
fun isDebug(): Boolean
|
||||
}
|
||||
|
||||
class DefaultBuildProvider() : BuildProvider {
|
||||
|
@ -15,4 +17,8 @@ class DefaultBuildProvider() : BuildProvider {
|
|||
override fun getModel(): String {
|
||||
return Build.MODEL
|
||||
}
|
||||
|
||||
override fun isDebug(): Boolean {
|
||||
return BuildConfig.DEBUG
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import com.anytypeio.anytype.core_models.exceptions.MigrationNeededException
|
|||
import com.anytypeio.anytype.core_utils.common.EventWrapper
|
||||
import com.anytypeio.anytype.domain.auth.interactor.SelectAccount
|
||||
import com.anytypeio.anytype.domain.device.PathProvider
|
||||
import com.anytypeio.anytype.CrashReporter
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
import com.anytypeio.anytype.presentation.navigation.AppNavigation
|
||||
|
@ -31,7 +32,8 @@ class SetupSelectedAccountViewModel(
|
|||
private val pathProvider: PathProvider,
|
||||
private val analytics: Analytics,
|
||||
private val relationsSubscriptionManager: RelationsSubscriptionManager,
|
||||
private val objectTypesSubscriptionManager: ObjectTypesSubscriptionManager
|
||||
private val objectTypesSubscriptionManager: ObjectTypesSubscriptionManager,
|
||||
private val crashReporter: com.anytypeio.anytype.CrashReporter
|
||||
) : ViewModel(), SupportNavigation<EventWrapper<AppNavigation.Command>> {
|
||||
|
||||
val isMigrationInProgress = MutableStateFlow(false)
|
||||
|
@ -72,6 +74,7 @@ class SetupSelectedAccountViewModel(
|
|||
success = { (analyticsId, status) ->
|
||||
migrationMessageJob.cancel()
|
||||
isMigrationInProgress.value = false
|
||||
crashReporter.setUser(analyticsId)
|
||||
updateUserProps(analyticsId)
|
||||
sendEvent(startTime)
|
||||
if (status is AccountStatus.PendingDeletion) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModelProvider
|
|||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.domain.auth.interactor.SelectAccount
|
||||
import com.anytypeio.anytype.domain.device.PathProvider
|
||||
import com.anytypeio.anytype.CrashReporter
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
|
||||
|
@ -13,7 +14,8 @@ class SetupSelectedAccountViewModelFactory(
|
|||
private val pathProvider: PathProvider,
|
||||
private val analytics: Analytics,
|
||||
private val relationsSubscriptionManager: RelationsSubscriptionManager,
|
||||
private val objectTypesSubscriptionManager: ObjectTypesSubscriptionManager
|
||||
private val objectTypesSubscriptionManager: ObjectTypesSubscriptionManager,
|
||||
private val crashReporter: com.anytypeio.anytype.CrashReporter
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -23,7 +25,8 @@ class SetupSelectedAccountViewModelFactory(
|
|||
pathProvider = pathProvider,
|
||||
analytics = analytics,
|
||||
relationsSubscriptionManager = relationsSubscriptionManager,
|
||||
objectTypesSubscriptionManager = objectTypesSubscriptionManager
|
||||
objectTypesSubscriptionManager = objectTypesSubscriptionManager,
|
||||
crashReporter = crashReporter
|
||||
) as T
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ import com.anytypeio.anytype.domain.auth.interactor.LaunchWallet
|
|||
import com.anytypeio.anytype.domain.auth.model.AuthStatus
|
||||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
import com.anytypeio.anytype.CrashReporter
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
|
@ -42,7 +43,8 @@ class SplashViewModel(
|
|||
private val createObject: CreateObject,
|
||||
private val relationsSubscriptionManager: RelationsSubscriptionManager,
|
||||
private val objectTypesSubscriptionManager: ObjectTypesSubscriptionManager,
|
||||
private val featureToggles: FeatureToggles
|
||||
private val featureToggles: FeatureToggles,
|
||||
private val crashReporter: com.anytypeio.anytype.CrashReporter
|
||||
) : ViewModel() {
|
||||
|
||||
val commands = MutableSharedFlow<Command>(replay = 0)
|
||||
|
@ -100,6 +102,7 @@ class SplashViewModel(
|
|||
viewModelScope.launch {
|
||||
launchAccount(BaseUseCase.None).proceed(
|
||||
success = { analyticsId ->
|
||||
crashReporter.setUser(analyticsId)
|
||||
updateUserProps(analyticsId)
|
||||
val props = Props.empty()
|
||||
sendEvent(startTime, openAccount, props)
|
||||
|
|
|
@ -8,9 +8,7 @@ import com.anytypeio.anytype.domain.auth.interactor.CheckAuthorizationStatus
|
|||
import com.anytypeio.anytype.domain.auth.interactor.GetLastOpenedObject
|
||||
import com.anytypeio.anytype.domain.auth.interactor.LaunchAccount
|
||||
import com.anytypeio.anytype.domain.auth.interactor.LaunchWallet
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.misc.AppActionManager
|
||||
import com.anytypeio.anytype.CrashReporter
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
|
@ -30,7 +28,8 @@ class SplashViewModelFactory @Inject constructor(
|
|||
private val createObject: CreateObject,
|
||||
private val relationsSubscriptionManager: RelationsSubscriptionManager,
|
||||
private val objectTypesSubscriptionManager: ObjectTypesSubscriptionManager,
|
||||
private val featureToggles: FeatureToggles
|
||||
private val featureToggles: FeatureToggles,
|
||||
private val crashReporter: com.anytypeio.anytype.CrashReporter
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -44,6 +43,7 @@ class SplashViewModelFactory @Inject constructor(
|
|||
createObject = createObject,
|
||||
relationsSubscriptionManager = relationsSubscriptionManager,
|
||||
objectTypesSubscriptionManager = objectTypesSubscriptionManager,
|
||||
featureToggles = featureToggles
|
||||
featureToggles = featureToggles,
|
||||
crashReporter = crashReporter
|
||||
) as T
|
||||
}
|
|
@ -13,6 +13,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
|||
import com.anytypeio.anytype.domain.config.ConfigStorage
|
||||
import com.anytypeio.anytype.domain.config.FeaturesConfigProvider
|
||||
import com.anytypeio.anytype.domain.device.PathProvider
|
||||
import com.anytypeio.anytype.CrashReporter
|
||||
import com.anytypeio.anytype.domain.`object`.ObjectTypesProvider
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
|
@ -71,6 +72,9 @@ class SetupSelectedAccountViewModelTest {
|
|||
|
||||
private lateinit var selectAccount: SelectAccount
|
||||
|
||||
@Mock
|
||||
private lateinit var crashReporter: com.anytypeio.anytype.CrashReporter
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.openMocks(this)
|
||||
|
@ -218,7 +222,8 @@ class SetupSelectedAccountViewModelTest {
|
|||
analytics = analytics,
|
||||
pathProvider = pathProvider,
|
||||
objectTypesSubscriptionManager = objectTypesSubscriptionManager,
|
||||
relationsSubscriptionManager = relationsSubscriptionManager
|
||||
relationsSubscriptionManager = relationsSubscriptionManager,
|
||||
crashReporter = crashReporter
|
||||
)
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ import com.anytypeio.anytype.domain.auth.model.AuthStatus
|
|||
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
|
||||
import com.anytypeio.anytype.domain.base.Either
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.CrashReporter
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
|
@ -68,6 +69,9 @@ class SplashViewModelTest {
|
|||
|
||||
@Mock lateinit var featureToggles: FeatureToggles
|
||||
|
||||
@Mock
|
||||
private lateinit var crashReporter: com.anytypeio.anytype.CrashReporter
|
||||
|
||||
lateinit var vm: SplashViewModel
|
||||
|
||||
@Before
|
||||
|
@ -89,7 +93,8 @@ class SplashViewModelTest {
|
|||
createObject = createObject,
|
||||
relationsSubscriptionManager = relationsSubscriptionManager,
|
||||
objectTypesSubscriptionManager = objectTypesSubscriptionManager,
|
||||
featureToggles = featureToggles
|
||||
featureToggles = featureToggles,
|
||||
crashReporter = crashReporter
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.anytypeio.anytype.ui_settings.about
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
@ -10,11 +11,14 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_ui.foundation.Divider
|
||||
import com.anytypeio.anytype.core_ui.foundation.Dragger
|
||||
import com.anytypeio.anytype.core_ui.views.Caption1Regular
|
||||
import com.anytypeio.anytype.core_ui.views.Caption2Regular
|
||||
import com.anytypeio.anytype.core_ui.views.Title1
|
||||
import com.anytypeio.anytype.core_ui.views.UXBody
|
||||
import com.anytypeio.anytype.ui_settings.R
|
||||
|
@ -22,7 +26,8 @@ import com.anytypeio.anytype.ui_settings.R
|
|||
@Composable
|
||||
fun AboutAppScreen(
|
||||
libraryVersion: String,
|
||||
anytypeId: String,
|
||||
accountId: String,
|
||||
analyticsId: String,
|
||||
version: String,
|
||||
buildNumber: Int,
|
||||
onMetaClicked: () -> Unit,
|
||||
|
@ -41,7 +46,7 @@ fun AboutAppScreen(
|
|||
.align(Alignment.CenterHorizontally)
|
||||
.padding(
|
||||
top = 18.dp,
|
||||
bottom = 16.dp
|
||||
bottom = 12.dp
|
||||
)
|
||||
) {
|
||||
Text(
|
||||
|
@ -72,13 +77,22 @@ fun AboutAppScreen(
|
|||
onExternalLinkClicked(AboutAppViewModel.ExternalLink.PrivacyPolicy)
|
||||
}
|
||||
Divider()
|
||||
Text(
|
||||
text = stringResource(R.string.tech_info),
|
||||
style = Caption1Regular,
|
||||
color = colorResource(R.color.text_secondary),
|
||||
modifier = Modifier.padding(
|
||||
top = 26.dp,
|
||||
start = 20.dp
|
||||
)
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
onMetaClicked()
|
||||
}
|
||||
.padding(
|
||||
top = 26.dp,
|
||||
top = 16.dp,
|
||||
start = 20.dp,
|
||||
end = 20.dp,
|
||||
bottom = 20.dp
|
||||
|
@ -90,9 +104,10 @@ fun AboutAppScreen(
|
|||
version,
|
||||
buildNumber,
|
||||
libraryVersion,
|
||||
anytypeId
|
||||
accountId,
|
||||
analyticsId
|
||||
),
|
||||
style = Caption1Regular.copy(
|
||||
style = Caption2Regular.copy(
|
||||
color = colorResource(id = R.color.text_secondary)
|
||||
)
|
||||
)
|
||||
|
@ -116,6 +131,11 @@ fun Option(
|
|||
text = title,
|
||||
style = UXBody.copy(color = colorResource(id = R.color.text_primary))
|
||||
)
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_arrow_forward),
|
||||
contentDescription = "Arrow Forward",
|
||||
modifier = Modifier.align(Alignment.CenterEnd)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,4 +150,18 @@ fun Section(
|
|||
style = Caption1Regular.copy(color = colorResource(id = R.color.text_secondary))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreviewAboutAppScreen() {
|
||||
AboutAppScreen(
|
||||
libraryVersion = "1.0.0",
|
||||
accountId = "1234567890",
|
||||
analyticsId = "1234567890",
|
||||
version = "1.0.0",
|
||||
buildNumber = 1,
|
||||
onMetaClicked = {},
|
||||
onExternalLinkClicked = {}
|
||||
)
|
||||
}
|
|
@ -9,6 +9,8 @@ import com.anytypeio.anytype.analytics.props.Props
|
|||
import com.anytypeio.anytype.domain.auth.interactor.GetAccount
|
||||
import com.anytypeio.anytype.domain.auth.interactor.GetLibraryVersion
|
||||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
import com.anytypeio.anytype.domain.config.ConfigStorage
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -16,7 +18,8 @@ import kotlinx.coroutines.launch
|
|||
class AboutAppViewModel(
|
||||
private val getAccount: GetAccount,
|
||||
private val getLibraryVersion: GetLibraryVersion,
|
||||
private val analytics: Analytics
|
||||
private val analytics: Analytics,
|
||||
private val configStorage: ConfigStorage
|
||||
) : ViewModel() {
|
||||
|
||||
val navigation = MutableSharedFlow<Navigation>()
|
||||
|
@ -40,17 +43,22 @@ class AboutAppViewModel(
|
|||
}
|
||||
|
||||
val libraryVersion = MutableStateFlow("")
|
||||
val userId = MutableStateFlow("")
|
||||
val accountId = MutableStateFlow("")
|
||||
val analyticsId = MutableStateFlow("")
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
getAccount(BaseUseCase.None).process(
|
||||
failure = {},
|
||||
success = { acc ->
|
||||
userId.value = acc.id
|
||||
accountId.value = acc.id
|
||||
}
|
||||
)
|
||||
}
|
||||
viewModelScope.launch {
|
||||
val config = configStorage.get()
|
||||
analyticsId.value = config.analytics
|
||||
}
|
||||
viewModelScope.launch {
|
||||
getLibraryVersion(BaseUseCase.None).process(
|
||||
failure = {},
|
||||
|
@ -92,10 +100,11 @@ class AboutAppViewModel(
|
|||
)
|
||||
}
|
||||
|
||||
class Factory(
|
||||
class Factory @Inject constructor(
|
||||
private val getAccount: GetAccount,
|
||||
private val getLibraryVersion: GetLibraryVersion,
|
||||
private val analytics: Analytics
|
||||
private val analytics: Analytics,
|
||||
private val configStorage: ConfigStorage
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -103,7 +112,8 @@ class AboutAppViewModel(
|
|||
return AboutAppViewModel(
|
||||
getAccount = getAccount,
|
||||
getLibraryVersion = getLibraryVersion,
|
||||
analytics = analytics
|
||||
analytics = analytics,
|
||||
configStorage = configStorage
|
||||
) as T
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
<string name="pin_code">Pin code</string>
|
||||
<string name="access">Access</string>
|
||||
<string name="wallpaper">Wallpaper</string>
|
||||
<string name="tech_info">Tech info</string>
|
||||
|
||||
<string name="light">Light</string>
|
||||
<string name="dark">Dark</string>
|
||||
|
@ -50,8 +51,8 @@
|
|||
<string name="about_terms_and_conditions_link">https://anytype.io/terms.pdf</string>
|
||||
<string name="about_privacy_policy_link">https://anytype.io/Anytype_Privacy_Statement.pdf</string>
|
||||
|
||||
<string name="about_meta_info">App version: %1$s\nBuild number: %2$d\nLibrary: %3$s\nUser\u00A0ID:\u00A0%4$s</string>
|
||||
<string name="about_meta_info_for_copy">Device: %1$s\nAndroid version: %2$d\nApp version: %3$s\nBuild number: %4$d\nLibrary: %5$s\nUser\u00A0ID:\u00A0%6$s</string>
|
||||
<string name="about_meta_info">App version: %1$s\nBuild number: %2$d\nLibrary version: %3$s\nAccount\u00A0ID:\u00A0%4$s\nAnalytics\u00A0ID:\u00A0%5$s</string>
|
||||
<string name="about_meta_info_for_copy">Device: %1$s\nAndroid version: %2$d\nApp version: %3$s\nBuild number: %4$d\nLibrary version: %5$s\nAccount\u00A0ID:\u00A0%6$s\nAnalytics\u00A0ID:\u00A0%7$s</string>
|
||||
<string name="space_name">Space name</string>
|
||||
<string name="personal_space">Personal Space</string>
|
||||
<string name="you_can_store">You can store up to %1$s of your files on our\nencrypted backup node for free. If you reach the\nlimit, files will be stored only locally.</string>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue