From 0b1936a78f57ca034fb8b022dc571f84631b0fd8 Mon Sep 17 00:00:00 2001 From: Evgenii Kozlov Date: Thu, 13 Jul 2023 19:45:12 +0200 Subject: [PATCH] DROID-1451 Space | Enhancement | Move 'Space debug' button to the 'Space' screen + Refact (#197) --- .../di/feature/settings/MainSettingsDi.kt | 44 +++++++++--- .../ui/settings/MainSettingFragment.kt | 23 +++++- .../anytype/ui/settings/ProfileFragment.kt | 2 +- .../anytypeio/anytype/core_models/Alias.kt | 1 + .../core_utils/ext/AndroidExtension.kt | 2 +- .../util/downloader/UriFileProvider.kt | 3 +- .../other/DebugSpaceDeviceContentSaver.kt | 5 ++ device/build.gradle | 3 + .../share/debug/DebugSpaceContentSaver.kt | 70 +++++++++++++++++++ .../anytype/domain/debugging/DebugSpace.kt | 3 +- .../debugging/DebugSpaceContentSaver.kt | 7 ++ .../domain/debugging/DebugSpaceDownloader.kt | 18 +++++ .../settings/MainSettingsViewModel.kt | 37 +++++++--- .../repo/DebugSpaceFileContentSaver.kt | 1 + .../account/repo/DebugSpaceShareDownloader.kt | 1 + .../ui_settings/main/MainSettingScreen.kt | 6 ++ 16 files changed, 201 insertions(+), 25 deletions(-) create mode 100644 data/src/main/java/com/anytypeio/anytype/data/auth/other/DebugSpaceDeviceContentSaver.kt create mode 100644 device/src/main/java/com/anytypeio/anytype/device/share/debug/DebugSpaceContentSaver.kt create mode 100644 domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugSpaceContentSaver.kt create mode 100644 domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugSpaceDownloader.kt diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/settings/MainSettingsDi.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/settings/MainSettingsDi.kt index ad43b27220..bfbed91b6a 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/settings/MainSettingsDi.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/settings/MainSettingsDi.kt @@ -2,21 +2,32 @@ package com.anytypeio.anytype.di.feature.settings import com.anytypeio.anytype.analytics.base.Analytics import com.anytypeio.anytype.core_utils.di.scope.PerScreen +import com.anytypeio.anytype.device.share.debug.DebugSpaceDeviceFileContentSaver import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers import com.anytypeio.anytype.domain.block.repo.BlockRepository import com.anytypeio.anytype.domain.config.ConfigStorage +import com.anytypeio.anytype.domain.debugging.DebugSpaceContentSaver +import com.anytypeio.anytype.domain.debugging.DebugSpaceShareDownloader import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer import com.anytypeio.anytype.domain.misc.UrlBuilder import com.anytypeio.anytype.domain.`object`.SetObjectDetails import com.anytypeio.anytype.domain.search.SubscriptionEventChannel import com.anytypeio.anytype.presentation.settings.MainSettingsViewModel import com.anytypeio.anytype.presentation.spaces.SpaceGradientProvider +import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider +import com.anytypeio.anytype.providers.DefaultUriFileProvider import com.anytypeio.anytype.ui.settings.MainSettingFragment +import dagger.Binds import dagger.Module import dagger.Provides import dagger.Subcomponent -@Subcomponent(modules = [MainSettingsModule::class]) +@Subcomponent( + modules = [ + MainSettingsModule::class, + MainSettingsModule.Bindings::class + ] +) @PerScreen interface MainSettingsSubComponent { @@ -70,13 +81,30 @@ object MainSettingsModule { configStorage: ConfigStorage, urlBuilder: UrlBuilder, setObjectDetails: SetObjectDetails, - spaceGradientProvider: SpaceGradientProvider + spaceGradientProvider: SpaceGradientProvider, + debugSpaceShareDownloader: DebugSpaceShareDownloader ): MainSettingsViewModel.Factory = MainSettingsViewModel.Factory( - analytics, - storelessSubscriptionContainer, - configStorage, - urlBuilder, - setObjectDetails, - spaceGradientProvider + analytics = analytics, + storelessSubscriptionContainer = storelessSubscriptionContainer, + configStorage = configStorage, + urlBuilder = urlBuilder, + setObjectDetails = setObjectDetails, + spaceGradientProvider = spaceGradientProvider, + debugSpaceShareDownloader = debugSpaceShareDownloader ) + + @Module + interface Bindings { + @PerScreen + @Binds + fun bindUriFileProvider( + defaultProvider: DefaultUriFileProvider + ): UriFileProvider + + @PerScreen + @Binds + fun bindSpaceDebugDeviceSharer( + saver: DebugSpaceDeviceFileContentSaver + ): DebugSpaceContentSaver + } } \ No newline at end of file diff --git a/app/src/main/java/com/anytypeio/anytype/ui/settings/MainSettingFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/settings/MainSettingFragment.kt index 58d24fc940..7576839616 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/settings/MainSettingFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/settings/MainSettingFragment.kt @@ -16,6 +16,7 @@ import androidx.lifecycle.repeatOnLifecycle import com.anytypeio.anytype.R import com.anytypeio.anytype.core_ui.common.ComposeDialogView import com.anytypeio.anytype.core_utils.ext.setupBottomSheetBehavior +import com.anytypeio.anytype.core_utils.ext.shareFile import com.anytypeio.anytype.core_utils.ext.toast import com.anytypeio.anytype.core_utils.tools.FeatureToggles import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment @@ -23,12 +24,15 @@ import com.anytypeio.anytype.di.common.componentManager import com.anytypeio.anytype.presentation.settings.MainSettingsViewModel import com.anytypeio.anytype.presentation.settings.MainSettingsViewModel.Command import com.anytypeio.anytype.presentation.settings.MainSettingsViewModel.Event +import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider import com.anytypeio.anytype.ui.editor.modals.IconPickerFragmentBase.Companion.ARG_CONTEXT_ID_KEY import com.anytypeio.anytype.ui.sets.ARG_SHOW_REMOVE_BUTTON import com.anytypeio.anytype.ui.settings.system.SettingsActivity import com.anytypeio.anytype.ui_settings.main.MainSettingScreen -import kotlinx.coroutines.launch +import java.io.File import javax.inject.Inject +import kotlinx.coroutines.launch +import timber.log.Timber class MainSettingFragment : BaseBottomSheetComposeFragment() { @@ -38,6 +42,9 @@ class MainSettingFragment : BaseBottomSheetComposeFragment() { @Inject lateinit var featureToggles: FeatureToggles + @Inject + lateinit var uriFileProvider: UriFileProvider + private val vm by viewModels { factory } private val onProfileClicked = { @@ -135,13 +142,23 @@ class MainSettingFragment : BaseBottomSheetComposeFragment() { ) ) } - Command.OpenFilesStorageScreen -> { + is Command.OpenFilesStorageScreen -> { safeNavigate(R.id.actionOpenFilesStorageScreen) } - is Command.Toast -> { toast(msg = command.msg) } + is Command.ShareSpaceDebug -> { + try { + shareFile( + uriFileProvider.getUriForFile(File(command.path)) + ) + } catch (e: Exception) { + Timber.e(e, "Error while sharing space debug").also { + toast("Error while sharing space debug. Please try again later.") + } + } + } } } diff --git a/app/src/main/java/com/anytypeio/anytype/ui/settings/ProfileFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/settings/ProfileFragment.kt index 4ed56b73a7..eb91732c59 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/settings/ProfileFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/settings/ProfileFragment.kt @@ -79,7 +79,7 @@ class ProfileFragment : BaseBottomSheetComposeFragment() { onSpaceDebugClicked = { throttle { vm.onSpaceDebugClicked() } }, isLogoutInProgress = vm.isLoggingOut.collectAsState().value, isDebugSpaceReportInProgress = vm.isDebugSpaceReportInProgress.collectAsState().value, - isShowDebug = true, + isShowDebug = false, onNameChange = { vm.onNameChange(it) }, onProfileIconClick = { proceedWithIconClick() }, account = vm.profileData.collectAsStateWithLifecycle().value, diff --git a/core-models/src/main/java/com/anytypeio/anytype/core_models/Alias.kt b/core-models/src/main/java/com/anytypeio/anytype/core_models/Alias.kt index 7f79f803cb..f2a0eba762 100644 --- a/core-models/src/main/java/com/anytypeio/anytype/core_models/Alias.kt +++ b/core-models/src/main/java/com/anytypeio/anytype/core_models/Alias.kt @@ -6,6 +6,7 @@ typealias Url = String typealias Hash = String typealias Struct = Map typealias Name = String +typealias Filepath = String typealias Document = List 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 cf8b94b741..c1ac3ebe3f 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 @@ -48,9 +48,9 @@ import com.anytypeio.anytype.core_utils.const.FileConstants.REQUEST_MEDIA_CODE import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog -import timber.log.Timber import java.text.SimpleDateFormat import java.util.* +import timber.log.Timber fun Context.dimen(res: Int): Float { return resources diff --git a/core-utils/src/main/java/com/anytypeio/anytype/presentation/util/downloader/UriFileProvider.kt b/core-utils/src/main/java/com/anytypeio/anytype/presentation/util/downloader/UriFileProvider.kt index c57ba5c0aa..ec2c8125d3 100644 --- a/core-utils/src/main/java/com/anytypeio/anytype/presentation/util/downloader/UriFileProvider.kt +++ b/core-utils/src/main/java/com/anytypeio/anytype/presentation/util/downloader/UriFileProvider.kt @@ -3,8 +3,7 @@ package com.anytypeio.anytype.presentation.util.downloader import android.net.Uri import java.io.File +// TODO move to device module interface UriFileProvider { - fun getUriForFile(file: File): Uri - } \ No newline at end of file diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/other/DebugSpaceDeviceContentSaver.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/other/DebugSpaceDeviceContentSaver.kt new file mode 100644 index 0000000000..e670f819d0 --- /dev/null +++ b/data/src/main/java/com/anytypeio/anytype/data/auth/other/DebugSpaceDeviceContentSaver.kt @@ -0,0 +1,5 @@ +package com.anytypeio.anytype.data.auth.other + +import com.anytypeio.anytype.domain.debugging.DebugSpaceContentSaver + +interface DebugSpaceDeviceContentSaver : DebugSpaceContentSaver \ No newline at end of file diff --git a/device/build.gradle b/device/build.gradle index bf634b31cb..52da2a994c 100644 --- a/device/build.gradle +++ b/device/build.gradle @@ -6,6 +6,7 @@ plugins { dependencies { implementation project(':data') + implementation project(':domain') implementation libs.kotlin implementation libs.coroutinesAndroid @@ -17,4 +18,6 @@ dependencies { testImplementation libs.kotlinTest testImplementation libs.androidXTestCore testImplementation libs.robolectric + + compileOnly libs.javaxInject } \ No newline at end of file diff --git a/device/src/main/java/com/anytypeio/anytype/device/share/debug/DebugSpaceContentSaver.kt b/device/src/main/java/com/anytypeio/anytype/device/share/debug/DebugSpaceContentSaver.kt new file mode 100644 index 0000000000..561205f67a --- /dev/null +++ b/device/src/main/java/com/anytypeio/anytype/device/share/debug/DebugSpaceContentSaver.kt @@ -0,0 +1,70 @@ +package com.anytypeio.anytype.device.share.debug + +import android.content.Context +import com.anytypeio.anytype.data.auth.other.DebugSpaceDeviceContentSaver +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Locale +import javax.inject.Inject + +class DebugSpaceDeviceFileContentSaver @Inject constructor( + private val context: Context +) : DebugSpaceDeviceContentSaver { + + @Throws(IOException::class) + override fun save(content: String): File { + val cacheDir = context.cacheDir + + require(cacheDir != null) { "Impossible to cache files!" } + + val filename = getFileName() + + // Creating folder + + val downloadFolder = File("${cacheDir.path}/$FOLDER_NAME/").apply { + mkdirs() + } + + val resultFilePath = "${cacheDir.path}/$FOLDER_NAME/${filename}" + val resultFile = File(resultFilePath) + + // Writing content + + val tempFileFolderPath = "${downloadFolder.absolutePath}/$TEMP_FOLDER_NAME" + val tempDir = File(tempFileFolderPath) + if (tempDir.exists()) tempDir.deleteRecursively() + tempDir.mkdirs() + + val tempResult = File(tempFileFolderPath, filename) + + FileOutputStream(tempResult).use { stream -> + stream.write(content.toByteArray()) + } + + tempResult.renameTo(resultFile) + + // Clearing + + tempDir.deleteRecursively() + + // Sending file + + return resultFile + } + + private fun getFileName(): String { + val date = Calendar.getInstance().time + val dateFormat = SimpleDateFormat(DATE_FORMAT, Locale.getDefault()) + val formattedDate = dateFormat.format(date) + return "DebugSpace$formattedDate.txt" + } + + companion object { + const val FOLDER_NAME = "debug_space" + const val TEMP_FOLDER_NAME = "tmp" + const val DATE_FORMAT = "dd-MM-yyyy-HH:mm:ss" + } +} \ No newline at end of file diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugSpace.kt b/domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugSpace.kt index 8fa6c5c898..94b1d50d41 100644 --- a/domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugSpace.kt +++ b/domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugSpace.kt @@ -3,8 +3,9 @@ package com.anytypeio.anytype.domain.debugging import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers import com.anytypeio.anytype.domain.base.ResultInteractor import com.anytypeio.anytype.domain.block.repo.BlockRepository +import javax.inject.Inject -class DebugSpace( +class DebugSpace @Inject constructor( private val repo: BlockRepository, dispatchers: AppCoroutineDispatchers ) : ResultInteractor(dispatchers.io) { diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugSpaceContentSaver.kt b/domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugSpaceContentSaver.kt new file mode 100644 index 0000000000..6ee90d21db --- /dev/null +++ b/domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugSpaceContentSaver.kt @@ -0,0 +1,7 @@ +package com.anytypeio.anytype.domain.debugging + +import java.io.File + +interface DebugSpaceContentSaver { + fun save(content: String) : File +} \ No newline at end of file diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugSpaceDownloader.kt b/domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugSpaceDownloader.kt new file mode 100644 index 0000000000..5f03db09d6 --- /dev/null +++ b/domain/src/main/java/com/anytypeio/anytype/domain/debugging/DebugSpaceDownloader.kt @@ -0,0 +1,18 @@ +package com.anytypeio.anytype.domain.debugging + +import com.anytypeio.anytype.core_models.Filepath +import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers +import com.anytypeio.anytype.domain.base.ResultInteractor +import javax.inject.Inject + +class DebugSpaceShareDownloader @Inject constructor( + private val debugSpace: DebugSpace, + private val debugSpaceContentSaver: DebugSpaceContentSaver, + dispatchers: AppCoroutineDispatchers, +) : ResultInteractor(dispatchers.io) { + override suspend fun doWork(params: Unit): Filepath { + val content = debugSpace.run(Unit) + val file = debugSpaceContentSaver.save(content = content) + return file.path + } +} \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/settings/MainSettingsViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/settings/MainSettingsViewModel.kt index a2bb065e21..db8f5b2456 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/settings/MainSettingsViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/settings/MainSettingsViewModel.kt @@ -1,22 +1,22 @@ package com.anytypeio.anytype.presentation.settings -import android.os.Build import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import com.anytypeio.anytype.analytics.base.Analytics import com.anytypeio.anytype.analytics.base.EventsDictionary import com.anytypeio.anytype.analytics.base.sendEvent +import com.anytypeio.anytype.core_models.Filepath import com.anytypeio.anytype.core_models.Id import com.anytypeio.anytype.core_models.Relations import com.anytypeio.anytype.core_utils.ext.throttleFirst import com.anytypeio.anytype.domain.base.fold import com.anytypeio.anytype.domain.config.ConfigStorage +import com.anytypeio.anytype.domain.debugging.DebugSpaceShareDownloader import com.anytypeio.anytype.domain.library.StoreSearchByIdsParams import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer import com.anytypeio.anytype.domain.misc.UrlBuilder import com.anytypeio.anytype.domain.`object`.SetObjectDetails -import com.anytypeio.anytype.presentation.BuildConfig import com.anytypeio.anytype.presentation.profile.ProfileIconView import com.anytypeio.anytype.presentation.profile.profileIcon import com.anytypeio.anytype.presentation.spaces.SpaceGradientProvider @@ -37,7 +37,8 @@ class MainSettingsViewModel( private val configStorage: ConfigStorage, private val urlBuilder: UrlBuilder, private val setObjectDetails: SetObjectDetails, - private val spaceGradientProvider: SpaceGradientProvider + private val spaceGradientProvider: SpaceGradientProvider, + private val debugSpaceShareDownloader: DebugSpaceShareDownloader ) : ViewModel() { val events = MutableSharedFlow(replay = 0) @@ -99,7 +100,9 @@ class MainSettingsViewModel( Event.OnProfileClicked -> commands.emit(Command.OpenProfileScreen) Event.OnAppearanceClicked -> commands.emit(Command.OpenAppearanceScreen) Event.OnPersonalizationClicked -> commands.emit(Command.OpenPersonalizationScreen) - Event.OnDebugClicked -> commands.emit(Command.OpenDebugScreen) + Event.OnDebugClicked -> { + proceedWithSpaceDebug() + } Event.OnSpaceImageClicked -> commands.emit( Command.OpenSpaceImageSet( configStorage.get().workspace @@ -111,6 +114,22 @@ class MainSettingsViewModel( } } + private fun proceedWithSpaceDebug() { + viewModelScope.launch { + debugSpaceShareDownloader + .stream(Unit) + .collect { result -> + result.fold( + onSuccess = { path -> + commands.emit( + Command.ShareSpaceDebug(path) + ) + } + ) + } + } + } + private fun dispatchAnalyticEvent(event: Event) { when (event) { Event.OnAboutClicked -> { @@ -178,7 +197,8 @@ class MainSettingsViewModel( private val configStorage: ConfigStorage, private val urlBuilder: UrlBuilder, private val setObjectDetails: SetObjectDetails, - private val spaceGradientProvider: SpaceGradientProvider + private val spaceGradientProvider: SpaceGradientProvider, + private val debugSpaceShareDownloader: DebugSpaceShareDownloader ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create( @@ -189,7 +209,8 @@ class MainSettingsViewModel( configStorage = configStorage, urlBuilder = urlBuilder, setObjectDetails = setObjectDetails, - spaceGradientProvider = spaceGradientProvider + spaceGradientProvider = spaceGradientProvider, + debugSpaceShareDownloader = debugSpaceShareDownloader ) as T } @@ -212,6 +233,7 @@ class MainSettingsViewModel( class OpenSpaceImageSet(val id: Id) : Command() object OpenFilesStorageScreen : Command() data class Toast(val msg: String) : Command() + data class ShareSpaceDebug(val path: Filepath): Command() } sealed class WorkspaceAndAccount { @@ -230,10 +252,7 @@ class MainSettingsViewModel( val name: String, val icon: ProfileIconView, ) - } - - } const val SPACE_STORAGE_SUBSCRIPTION_ID = "settings_space_storage_subscription" diff --git a/ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/account/repo/DebugSpaceFileContentSaver.kt b/ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/account/repo/DebugSpaceFileContentSaver.kt index d0ef3ada72..1e5e8d4d79 100644 --- a/ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/account/repo/DebugSpaceFileContentSaver.kt +++ b/ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/account/repo/DebugSpaceFileContentSaver.kt @@ -6,6 +6,7 @@ import com.anytypeio.anytype.domain.base.ResultInteractor import java.io.File import java.io.FileOutputStream +@Deprecated("To be deleted") class DebugSpaceFileContentSaver( private val context: Context, dispatchers: AppCoroutineDispatchers, diff --git a/ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/account/repo/DebugSpaceShareDownloader.kt b/ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/account/repo/DebugSpaceShareDownloader.kt index ce048d5cd9..3a9bd5c959 100644 --- a/ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/account/repo/DebugSpaceShareDownloader.kt +++ b/ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/account/repo/DebugSpaceShareDownloader.kt @@ -9,6 +9,7 @@ import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale +@Deprecated("To be deleted") class DebugSpaceShareDownloader( private val debugSpace: DebugSpace, private val fileSaver: DebugSpaceFileContentSaver, diff --git a/ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/main/MainSettingScreen.kt b/ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/main/MainSettingScreen.kt index 06df2269a2..c7f4beef8a 100644 --- a/ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/main/MainSettingScreen.kt +++ b/ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/main/MainSettingScreen.kt @@ -114,6 +114,12 @@ private fun Settings( onClick = onFileStorageClick ) Divider(paddingStart = 60.dp) + Option( + image = R.drawable.ic_debug, + text = stringResource(R.string.space_debug), + onClick = onDebugClicked + ) + Divider(paddingStart = 60.dp) Option( image = R.drawable.ic_about, text = stringResource(R.string.about),