From 963603f0f8a50e6d90fecdbe67903de88f1fdf8d Mon Sep 17 00:00:00 2001
From: Konstantin Ivanov <54908981+konstantiniiv@users.noreply.github.com>
Date: Fri, 20 Dec 2024 12:20:16 +0100
Subject: [PATCH] DROID-3164 Tech | Support debug log sharing (#1943)
---
.../anytype/di/feature/AppPreferencesDi.kt | 23 ++++++-
.../OnboardingNetworkSetupDialog.kt | 28 ++++++++-
.../signin/OnboardingNetworkSetupScreen.kt | 26 +++-----
app/src/main/res/xml/provider_paths.xml | 1 +
.../anytypeio/anytype/core_models/Command.kt | 3 +-
.../core_utils/ext/AndroidExtension.kt | 15 +++++
.../data/auth/repo/AuthCacheDataStore.kt | 4 ++
.../data/auth/repo/AuthDataRepository.kt | 4 ++
.../anytype/data/auth/repo/AuthDataStore.kt | 1 +
.../anytype/data/auth/repo/AuthRemote.kt | 1 +
.../data/auth/repo/AuthRemoteDataStore.kt | 4 ++
.../domain/auth/interactor/CreateAccount.kt | 1 -
.../domain/auth/repo/AuthRepository.kt | 1 +
.../domain/debugging/DebugExportLogs.kt | 18 ++++++
localization/src/main/res/values/strings.xml | 1 +
.../anytype/middleware/auth/AuthMiddleware.kt | 4 ++
.../middleware/interactor/Middleware.kt | 12 +++-
.../middleware/service/MiddlewareService.kt | 3 +
.../MiddlewareServiceImplementation.kt | 13 ++++
.../settings/PreferencesViewModel.kt | 63 +++++++++++++++----
20 files changed, 189 insertions(+), 37 deletions(-)
create mode 100644 domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugExportLogs.kt
diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/AppPreferencesDi.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/AppPreferencesDi.kt
index 70a17b131b..d1e4c0c2a6 100644
--- a/app/src/main/java/com/anytypeio/anytype/di/feature/AppPreferencesDi.kt
+++ b/app/src/main/java/com/anytypeio/anytype/di/feature/AppPreferencesDi.kt
@@ -6,12 +6,15 @@ import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.di.common.ComponentDependencies
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
+import com.anytypeio.anytype.domain.debugging.DebugExportLogs
+import com.anytypeio.anytype.domain.device.PathProvider
import com.anytypeio.anytype.domain.networkmode.GetNetworkMode
import com.anytypeio.anytype.domain.networkmode.SetNetworkMode
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.settings.PreferencesViewModel
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
import com.anytypeio.anytype.presentation.util.NetworkModeCopyFileToCacheDirectory
+import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
import com.anytypeio.anytype.ui.onboarding.OnboardingNetworkSetupDialog
import com.anytypeio.anytype.ui.settings.system.PreferenceFragment
import dagger.Component
@@ -44,6 +47,14 @@ object AppPreferencesModule {
context: Context
): CopyFileToCacheDirectory = NetworkModeCopyFileToCacheDirectory(context)
+ @JvmStatic
+ @Provides
+ @PerScreen
+ fun provideLogsExport(
+ repository: AuthRepository,
+ dispatchers: AppCoroutineDispatchers
+ ): DebugExportLogs = DebugExportLogs(repository, dispatchers)
+
@JvmStatic
@Provides
@PerScreen
@@ -51,12 +62,18 @@ object AppPreferencesModule {
copyFileToCacheDirectory: CopyFileToCacheDirectory,
getNetworkMode: GetNetworkMode,
setNetworkMode: SetNetworkMode,
- analytics: Analytics
+ analytics: Analytics,
+ debugExportLogs: DebugExportLogs,
+ pathProvider: PathProvider,
+ urlFileProvider: UriFileProvider
): PreferencesViewModel.Factory = PreferencesViewModel.Factory(
copyFileToCacheDirectory = copyFileToCacheDirectory,
getNetworkMode = getNetworkMode,
setNetworkMode = setNetworkMode,
- analytics = analytics
+ analytics = analytics,
+ debugExportLogs = debugExportLogs,
+ pathProvider = pathProvider,
+ uriFileProvider = urlFileProvider
)
}
@@ -66,4 +83,6 @@ interface AppPreferencesDependencies : ComponentDependencies {
fun authRepository(): AuthRepository
fun analytics(): Analytics
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
+ fun pathProvider(): PathProvider
+ fun provideUriFileProvider(): UriFileProvider
}
\ No newline at end of file
diff --git a/app/src/main/java/com/anytypeio/anytype/ui/onboarding/OnboardingNetworkSetupDialog.kt b/app/src/main/java/com/anytypeio/anytype/ui/onboarding/OnboardingNetworkSetupDialog.kt
index f47974a1e3..8cc2e02b02 100644
--- a/app/src/main/java/com/anytypeio/anytype/ui/onboarding/OnboardingNetworkSetupDialog.kt
+++ b/app/src/main/java/com/anytypeio/anytype/ui/onboarding/OnboardingNetworkSetupDialog.kt
@@ -15,6 +15,8 @@ import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_models.NetworkModeConstants
import com.anytypeio.anytype.core_utils.const.FileConstants
import com.anytypeio.anytype.core_utils.ext.Mimetype
+import com.anytypeio.anytype.core_utils.ext.shareFileFromPath
+import com.anytypeio.anytype.core_utils.ext.subscribe
import com.anytypeio.anytype.core_utils.ext.toast
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
import com.anytypeio.anytype.di.common.componentManager
@@ -23,6 +25,7 @@ import com.anytypeio.anytype.ui.editor.PickerDelegate
import com.anytypeio.anytype.ui.onboarding.screens.signin.NetworkSetupScreen
import com.anytypeio.anytype.ui.settings.typography
import javax.inject.Inject
+import timber.log.Timber
class OnboardingNetworkSetupDialog : BaseBottomSheetComposeFragment() {
@@ -62,12 +65,35 @@ class OnboardingNetworkSetupDialog : BaseBottomSheetComposeFragment() {
onAnytypeNetworkClicked = {
vm.proceedWithNetworkMode(NetworkModeConstants.NETWORK_MODE_DEFAULT)
},
- onUseYamuxToggled = vm::onChangeMultiplexLibrary
+ onExportLogsClick = vm::onExportLogsClick
)
}
}
}
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ subscribe(vm.commands) { command ->
+ when (command) {
+ is PreferencesViewModel.Command.ShareDebugLogs -> {
+ try {
+ shareFileFromPath(
+ path = command.path,
+ uriFileProvider = command.uriFileProvider
+ )
+ } catch (e: Exception) {
+ Timber.e(e, "Error while share debug logs").also {
+ toast("Error while share debug logs. Please try again later.")
+ }
+ }
+ }
+ is PreferencesViewModel.Command.ShowToast -> {
+ toast(command.message)
+ }
+ }
+ }
+ }
+
private fun setup() {
pickerDelegate = PickerDelegate.Impl(this) { actions ->
when (actions) {
diff --git a/app/src/main/java/com/anytypeio/anytype/ui/onboarding/screens/signin/OnboardingNetworkSetupScreen.kt b/app/src/main/java/com/anytypeio/anytype/ui/onboarding/screens/signin/OnboardingNetworkSetupScreen.kt
index 4cd31fd9ba..b1f73a70e1 100644
--- a/app/src/main/java/com/anytypeio/anytype/ui/onboarding/screens/signin/OnboardingNetworkSetupScreen.kt
+++ b/app/src/main/java/com/anytypeio/anytype/ui/onboarding/screens/signin/OnboardingNetworkSetupScreen.kt
@@ -52,7 +52,7 @@ fun DefaultNetworkSetupScreenPreview() {
onLocalOnlyClicked = {},
onSelfHostNetworkClicked = {},
onSetSelfHostConfigConfigClicked = {},
- onUseYamuxToggled = {}
+ onExportLogsClick = {}
)
}
@@ -69,7 +69,7 @@ fun SelfHostNetworkSetupScreenPreview() {
onLocalOnlyClicked = {},
onSelfHostNetworkClicked = {},
onSetSelfHostConfigConfigClicked = {},
- onUseYamuxToggled = {}
+ onExportLogsClick = {}
)
}
@@ -86,7 +86,7 @@ fun SelfHostNetworkWithPathSetupScreenPreview() {
onLocalOnlyClicked = {},
onSelfHostNetworkClicked = {},
onSetSelfHostConfigConfigClicked = {},
- onUseYamuxToggled = {}
+ onExportLogsClick = {}
)
}
@@ -103,7 +103,7 @@ fun LocalNetworkWithPathSetupScreenPreview() {
onLocalOnlyClicked = {},
onSelfHostNetworkClicked = {},
onSetSelfHostConfigConfigClicked = {},
- onUseYamuxToggled = {}
+ onExportLogsClick = {}
)
}
@@ -114,7 +114,7 @@ fun NetworkSetupScreen(
onAnytypeNetworkClicked: () -> Unit,
onSelfHostNetworkClicked: () -> Unit,
onSetSelfHostConfigConfigClicked: () -> Unit,
- onUseYamuxToggled: () -> Unit
+ onExportLogsClick: () -> Unit
) {
Column(
modifier = Modifier
@@ -148,19 +148,19 @@ fun NetworkSetupScreen(
color = NetworkSettingDescriptionColor,
textPaddingStart = 0.dp
)
- UseYamuxCard(config = config, onUseYamuxToggled = onUseYamuxToggled)
+ ExportLogs(onExportLogsClick = onExportLogsClick)
Spacer(modifier = Modifier.height(24.dp))
}
}
@Composable
-private fun UseYamuxCard(config: NetworkModeConfig, onUseYamuxToggled: () -> Unit) {
+private fun ExportLogs(onExportLogsClick: () -> Unit) {
Column(
modifier = Modifier
.clip(RoundedCornerShape(16.dp))
.fillMaxWidth()
.background(color = NetworkSettingCardColor)
- .noRippleClickable { onUseYamuxToggled() }
+ .noRippleClickable { onExportLogsClick() }
) {
Row(
verticalAlignment = Alignment.CenterVertically,
@@ -170,19 +170,11 @@ private fun UseYamuxCard(config: NetworkModeConfig, onUseYamuxToggled: () -> Uni
)
) {
Text(
- text = stringResource(id = R.string.settings_use_yamux),
+ text = stringResource(id = R.string.settings_share_local_logs),
style = BodyCalloutRegular,
color = NetworkSettingTitleColor,
modifier = Modifier.weight(1.0f)
)
- if (config.useReserveMultiplexLib) {
- Image(
- painter = painterResource(id = R.drawable.ic_network_settings_checked),
- contentDescription = "Check icon"
- )
- } else {
- Spacer(modifier = Modifier.size(24.dp))
- }
}
}
}
diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml
index 4419d669d4..948ac11c51 100644
--- a/app/src/main/res/xml/provider_paths.xml
+++ b/app/src/main/res/xml/provider_paths.xml
@@ -1,4 +1,5 @@
+
\ No newline at end of file
diff --git a/core-models/src/main/java/com/anytypeio/anytype/core_models/Command.kt b/core-models/src/main/java/com/anytypeio/anytype/core_models/Command.kt
index 2b5bd485f5..680ea89542 100644
--- a/core-models/src/main/java/com/anytypeio/anytype/core_models/Command.kt
+++ b/core-models/src/main/java/com/anytypeio/anytype/core_models/Command.kt
@@ -13,8 +13,7 @@ sealed class Command {
val avatarPath: String?,
val icon: Int,
val networkMode: NetworkMode = NetworkMode.DEFAULT,
- val networkConfigFilePath: String? = null,
- val preferYamuxTransport: Boolean? = null
+ val networkConfigFilePath: String? = null
) : Command()
data class AccountSelect(
diff --git a/core-utils/src/main/java/com/anytypeio/anytype/core_utils/ext/AndroidExtension.kt b/core-utils/src/main/java/com/anytypeio/anytype/core_utils/ext/AndroidExtension.kt
index 5a0d8ae8f5..f8e86a81f5 100644
--- a/core-utils/src/main/java/com/anytypeio/anytype/core_utils/ext/AndroidExtension.kt
+++ b/core-utils/src/main/java/com/anytypeio/anytype/core_utils/ext/AndroidExtension.kt
@@ -386,6 +386,21 @@ fun Fragment.shareFirstFileFromPath(path: String, uriFileProvider: UriFileProvid
}
}
+fun Fragment.shareFileFromPath(path: String, uriFileProvider: UriFileProvider) {
+ try {
+ val dirPath = File(path)
+ if (dirPath.exists()) {
+ val uri = uriFileProvider.getUriForFile(dirPath)
+ shareFile(uri)
+ } else {
+ toast("File does not exist.")
+ }
+ } catch (e: Exception) {
+ Timber.e(e, "Error while sharing file")
+ toast("Could not share file: ${e.message}")
+ }
+}
+
fun Fragment.shareFile(uri: Uri) {
try {
val shareIntent: Intent = Intent().apply {
diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthCacheDataStore.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthCacheDataStore.kt
index 8c32ad6003..471c53c790 100644
--- a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthCacheDataStore.kt
+++ b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthCacheDataStore.kt
@@ -89,4 +89,8 @@ class AuthCacheDataStore(private val cache: AuthCache) : AuthDataStore {
override suspend fun setNetworkMode(modeConfig: NetworkModeConfig) {
cache.setNetworkMode(modeConfig)
}
+
+ override suspend fun debugExportLogs(dir: String): String {
+ throw UnsupportedOperationException()
+ }
}
\ No newline at end of file
diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthDataRepository.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthDataRepository.kt
index 4413f568c9..30a41ebe2f 100644
--- a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthDataRepository.kt
+++ b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthDataRepository.kt
@@ -100,4 +100,8 @@ class AuthDataRepository(
override suspend fun setNetworkMode(modeConfig: NetworkModeConfig) {
factory.cache.setNetworkMode(modeConfig)
}
+
+ override suspend fun debugExportLogs(dir: String): String {
+ return factory.remote.debugExportLogs(dir)
+ }
}
\ No newline at end of file
diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthDataStore.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthDataStore.kt
index 4dfc81f1d1..1b9b077ace 100644
--- a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthDataStore.kt
+++ b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthDataStore.kt
@@ -42,4 +42,5 @@ interface AuthDataStore {
suspend fun getNetworkMode(): NetworkModeConfig
suspend fun setNetworkMode(modeConfig: NetworkModeConfig)
+ suspend fun debugExportLogs(dir: String): String
}
\ No newline at end of file
diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthRemote.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthRemote.kt
index 73797a1839..9ec8e409bf 100644
--- a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthRemote.kt
+++ b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthRemote.kt
@@ -22,4 +22,5 @@ interface AuthRemote {
suspend fun getVersion(): String
suspend fun setInitialParams(command: Command.SetInitialParams)
+ suspend fun debugExportLogs(dir: String): String
}
\ No newline at end of file
diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthRemoteDataStore.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthRemoteDataStore.kt
index 5874dc03d0..6620b8478d 100644
--- a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthRemoteDataStore.kt
+++ b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/AuthRemoteDataStore.kt
@@ -89,4 +89,8 @@ class AuthRemoteDataStore(
override suspend fun setNetworkMode(modeConfig: NetworkModeConfig) {
throw UnsupportedOperationException()
}
+
+ override suspend fun debugExportLogs(dir: String): String {
+ return authRemote.debugExportLogs(dir)
+ }
}
\ No newline at end of file
diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/auth/interactor/CreateAccount.kt b/domain/src/main/java/com/anytypeio/anytype/domain/auth/interactor/CreateAccount.kt
index 5a82376292..c07fcfc1b2 100644
--- a/domain/src/main/java/com/anytypeio/anytype/domain/auth/interactor/CreateAccount.kt
+++ b/domain/src/main/java/com/anytypeio/anytype/domain/auth/interactor/CreateAccount.kt
@@ -35,7 +35,6 @@ open class CreateAccount @Inject constructor(
icon = params.iconGradientValue,
networkMode = networkMode.networkMode,
networkConfigFilePath = networkMode.storedFilePath,
- preferYamuxTransport = networkMode.useReserveMultiplexLib
)
val setup = repository.createAccount(command)
with(repository) {
diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/auth/repo/AuthRepository.kt b/domain/src/main/java/com/anytypeio/anytype/domain/auth/repo/AuthRepository.kt
index a18535619d..a0a40934ed 100644
--- a/domain/src/main/java/com/anytypeio/anytype/domain/auth/repo/AuthRepository.kt
+++ b/domain/src/main/java/com/anytypeio/anytype/domain/auth/repo/AuthRepository.kt
@@ -59,4 +59,5 @@ interface AuthRepository {
suspend fun getNetworkMode(): NetworkModeConfig
suspend fun setNetworkMode(modeConfig: NetworkModeConfig)
+ suspend fun debugExportLogs(dir: String): String
}
\ No newline at end of file
diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugExportLogs.kt b/domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugExportLogs.kt
new file mode 100644
index 0000000000..669320092b
--- /dev/null
+++ b/domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugExportLogs.kt
@@ -0,0 +1,18 @@
+package com.anytypeio.anytype.domain.debugging
+
+import com.anytypeio.anytype.domain.auth.repo.AuthRepository
+import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
+import com.anytypeio.anytype.domain.base.ResultInteractor
+import javax.inject.Inject
+
+class DebugExportLogs @Inject constructor(
+ private val repo: AuthRepository,
+ dispatchers: AppCoroutineDispatchers
+) : ResultInteractor(dispatchers.io) {
+
+ override suspend fun doWork(params: Params): String {
+ return repo.debugExportLogs(params.dir)
+ }
+
+ data class Params(val dir: String)
+}
\ No newline at end of file
diff --git a/localization/src/main/res/values/strings.xml b/localization/src/main/res/values/strings.xml
index 22958be181..163be429e3 100644
--- a/localization/src/main/res/values/strings.xml
+++ b/localization/src/main/res/values/strings.xml
@@ -1271,6 +1271,7 @@
%1$s days from now
Use a reserve multiplex library
+ Share local logs
diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/auth/AuthMiddleware.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/auth/AuthMiddleware.kt
index cd59a24609..78b5ac2d47 100644
--- a/middleware/src/main/java/com/anytypeio/anytype/middleware/auth/AuthMiddleware.kt
+++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/auth/AuthMiddleware.kt
@@ -75,4 +75,8 @@ class AuthMiddleware(
override suspend fun setInitialParams(command: Command.SetInitialParams) {
middleware.metricsSetParameters(command)
}
+
+ override suspend fun debugExportLogs(dir: String): String {
+ return middleware.debugExportLogs(dir)
+ }
}
\ No newline at end of file
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 65e9e0cf7b..7a57b6fd12 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
@@ -90,8 +90,7 @@ class Middleware @Inject constructor(
avatarLocalPath = command.avatarPath,
icon = command.icon.toLong(),
networkMode = command.networkMode.toMiddlewareModel(),
- networkCustomConfigFilePath = command.networkConfigFilePath.orEmpty(),
- preferYamuxTransport = command.preferYamuxTransport ?: false
+ networkCustomConfigFilePath = command.networkConfigFilePath.orEmpty()
)
logRequestIfDebug(request)
val (response, time) = measureTimedValue { service.accountCreate(request) }
@@ -2867,6 +2866,15 @@ class Middleware @Inject constructor(
logResponseIfDebug(response, time)
}
+ @Throws(Exception::class)
+ fun debugExportLogs(dir: String): String {
+ val request = Rpc.Debug.ExportLog.Request(dir = dir)
+ logRequestIfDebug(request)
+ val (response, time) = measureTimedValue { service.debugExportLogs(request) }
+ logResponseIfDebug(response, time)
+ return response.path
+ }
+
private fun logRequestIfDebug(request: Any) {
if (BuildConfig.DEBUG) {
logger.logRequest(request).also {
diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareService.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareService.kt
index fe9ff68f81..4a1851178d 100644
--- a/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareService.kt
+++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareService.kt
@@ -612,4 +612,7 @@ interface MiddlewareService {
@Throws(Exception::class)
fun deviceNetworkStateSet(request: Rpc.Device.NetworkState.Set.Request): Rpc.Device.NetworkState.Set.Response
+
+ @Throws(Exception::class)
+ fun debugExportLogs(request: Rpc.Debug.ExportLog.Request): Rpc.Debug.ExportLog.Response
}
\ No newline at end of file
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 c3078571fc..9ae9436eb2 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
@@ -2463,4 +2463,17 @@ class MiddlewareServiceImplementation @Inject constructor(
return response
}
}
+
+ override fun debugExportLogs(request: Rpc.Debug.ExportLog.Request): Rpc.Debug.ExportLog.Response {
+ val encoded = Service.debugExportLog(
+ Rpc.Debug.ExportLog.Request.ADAPTER.encode(request)
+ )
+ val response = Rpc.Debug.ExportLog.Response.ADAPTER.decode(encoded)
+ val error = response.error
+ if (error != null && error.code != Rpc.Debug.ExportLog.Response.Error.Code.NULL) {
+ throw Exception(error.description)
+ } else {
+ return response
+ }
+ }
}
\ No newline at end of file
diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/settings/PreferencesViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/settings/PreferencesViewModel.kt
index 94c2ac65ac..345d804d05 100644
--- a/presentation/src/main/java/com/anytypeio/anytype/presentation/settings/PreferencesViewModel.kt
+++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/settings/PreferencesViewModel.kt
@@ -11,7 +11,10 @@ import com.anytypeio.anytype.core_models.NetworkMode
import com.anytypeio.anytype.core_models.NetworkModeConfig
import com.anytypeio.anytype.core_models.NetworkModeConstants.NETWORK_MODE_CUSTOM
import com.anytypeio.anytype.core_models.NetworkModeConstants.NETWORK_MODE_LOCAL
+import com.anytypeio.anytype.core_utils.ext.cancel
import com.anytypeio.anytype.domain.base.fold
+import com.anytypeio.anytype.domain.debugging.DebugExportLogs
+import com.anytypeio.anytype.domain.device.PathProvider
import com.anytypeio.anytype.domain.networkmode.GetNetworkMode
import com.anytypeio.anytype.domain.networkmode.SetNetworkMode
import com.anytypeio.anytype.presentation.editor.picker.PickerListener
@@ -19,6 +22,9 @@ import com.anytypeio.anytype.presentation.extension.sendAnalyticsSelectNetworkEv
import com.anytypeio.anytype.presentation.extension.sendAnalyticsUploadConfigFileEvent
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
import com.anytypeio.anytype.presentation.util.CopyFileToCacheStatus
+import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import timber.log.Timber
@@ -27,12 +33,18 @@ class PreferencesViewModel(
private val copyFileToCache: CopyFileToCacheDirectory,
private val getNetworkMode: GetNetworkMode,
private val setNetworkMode: SetNetworkMode,
- private val analytics: Analytics
+ private val analytics: Analytics,
+ private val debugExportLogs: DebugExportLogs,
+ private val pathProvider: PathProvider,
+ private val uriFileProvider: UriFileProvider,
) : ViewModel(), PickerListener {
val networkModeState = MutableStateFlow(NetworkModeConfig(NetworkMode.DEFAULT, "", ""))
val reserveMultiplexSetting = MutableStateFlow(false)
+ private val jobs = mutableListOf()
+ val commands = MutableSharedFlow()
+
fun onStart() {
Timber.d("onStart")
viewModelScope.launch {
@@ -49,6 +61,11 @@ class PreferencesViewModel(
}
}
+ override fun onCleared() {
+ super.onCleared()
+ jobs.cancel()
+ }
+
fun proceedWithNetworkMode(mode: String?) {
viewModelScope.launch {
val config = when (mode) {
@@ -104,19 +121,30 @@ class PreferencesViewModel(
}
}
- fun onChangeMultiplexLibrary() {
- val newValue = !networkModeState.value.useReserveMultiplexLib
- Timber.d("onChangeMultiplexLibrary: $newValue")
- viewModelScope.launch {
- val mode = networkModeState.value.copy(useReserveMultiplexLib = newValue)
- val params = SetNetworkMode.Params(mode)
- setNetworkMode.async(params).fold(
- onSuccess = { networkModeState.value = mode },
- onFailure = { Timber.e(it, "Failed to update network mode ") }
+ fun onExportLogsClick() {
+ Timber.d("onExportLogsClick: ")
+ jobs += viewModelScope.launch {
+ val dir = pathProvider.providePath()
+ val params = DebugExportLogs.Params(dir = dir)
+ debugExportLogs.async(params).fold(
+ onSuccess = { fileName ->
+ Timber.d("On debug logs success")
+ sendCommand(Command.ShareDebugLogs(fileName, uriFileProvider))
+ },
+ onFailure = {
+ Timber.e(it, "Error while collecting debug logs")
+ sendCommand(Command.ShowToast("Error while collecting debug logs: "))
+ }
)
}
}
+ private fun sendCommand(command: Command) {
+ viewModelScope.launch {
+ commands.emit(command)
+ }
+ }
+
override fun onStartCopyFileToCacheDir(uri: Uri) {
Timber.d("onStartCopyFileToCacheDir: $uri")
copyFileToCache.execute(
@@ -145,11 +173,19 @@ class PreferencesViewModel(
}
}
+ sealed class Command {
+ data class ShowToast(val message: String) : Command()
+ data class ShareDebugLogs(val path: String, val uriFileProvider: UriFileProvider) : Command()
+ }
+
class Factory(
private val copyFileToCacheDirectory: CopyFileToCacheDirectory,
private val getNetworkMode: GetNetworkMode,
private val setNetworkMode: SetNetworkMode,
- private val analytics: Analytics
+ private val analytics: Analytics,
+ private val debugExportLogs: DebugExportLogs,
+ private val pathProvider: PathProvider,
+ private val uriFileProvider: UriFileProvider,
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun create(
@@ -158,7 +194,10 @@ class PreferencesViewModel(
copyFileToCache = copyFileToCacheDirectory,
getNetworkMode = getNetworkMode,
setNetworkMode = setNetworkMode,
- analytics = analytics
+ analytics = analytics,
+ debugExportLogs = debugExportLogs,
+ pathProvider = pathProvider,
+ uriFileProvider = uriFileProvider
) as T
}
}
\ No newline at end of file