mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-3164 Tech | Support debug log sharing (#1943)
This commit is contained in:
parent
410a15d224
commit
147f426d5d
20 changed files with 189 additions and 37 deletions
|
@ -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
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths>
|
||||
<cache-path name="." path="/" />
|
||||
<files-path name="." path="/" />
|
||||
</paths>
|
|
@ -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(
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -42,4 +42,5 @@ interface AuthDataStore {
|
|||
|
||||
suspend fun getNetworkMode(): NetworkModeConfig
|
||||
suspend fun setNetworkMode(modeConfig: NetworkModeConfig)
|
||||
suspend fun debugExportLogs(dir: String): String
|
||||
}
|
|
@ -22,4 +22,5 @@ interface AuthRemote {
|
|||
|
||||
suspend fun getVersion(): String
|
||||
suspend fun setInitialParams(command: Command.SetInitialParams)
|
||||
suspend fun debugExportLogs(dir: String): String
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -59,4 +59,5 @@ interface AuthRepository {
|
|||
|
||||
suspend fun getNetworkMode(): NetworkModeConfig
|
||||
suspend fun setNetworkMode(modeConfig: NetworkModeConfig)
|
||||
suspend fun debugExportLogs(dir: String): String
|
||||
}
|
|
@ -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<DebugExportLogs.Params, String>(dispatchers.io) {
|
||||
|
||||
override suspend fun doWork(params: Params): String {
|
||||
return repo.debugExportLogs(params.dir)
|
||||
}
|
||||
|
||||
data class Params(val dir: String)
|
||||
}
|
|
@ -1271,6 +1271,7 @@
|
|||
<string name="dates_days_from">%1$s days from now</string>
|
||||
|
||||
<string name="settings_use_yamux">Use a reserve multiplex library</string>
|
||||
<string name="settings_share_local_logs">Share local logs</string>
|
||||
|
||||
<!--endregion-->
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<Job>()
|
||||
val commands = MutableSharedFlow<Command>()
|
||||
|
||||
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 <T : ViewModel> 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
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue