1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

DROID-3375 New settings | Enhancement | Space tech info with copy-to-clipboard functionality (#2158)

This commit is contained in:
Evgenii Kozlov 2025-03-13 16:00:23 +01:00 committed by GitHub
parent d19f5a0ba4
commit e20f421900
Signed by: github
GPG key ID: B5690EEEBB952194
5 changed files with 196 additions and 12 deletions

View file

@ -3,7 +3,9 @@ package com.anytypeio.anytype.ui_settings.space.new_settings
import android.os.Build
import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
@ -28,6 +30,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
@ -40,7 +43,6 @@ import com.anytypeio.anytype.presentation.spaces.UiEvent
import com.anytypeio.anytype.presentation.spaces.UiSpaceSettingsItem
import com.anytypeio.anytype.presentation.spaces.UiSpaceSettingsState
import com.anytypeio.anytype.ui_settings.R
import timber.log.Timber
@Composable
fun SpaceSettingsContainer(
@ -66,6 +68,7 @@ fun NewSpaceSettingsScreen(
var showEditDescription by remember { mutableStateOf(false) }
var showEditTitle by remember { mutableStateOf(false) }
var showTechInfo by remember { mutableStateOf(false) }
Scaffold(
modifier = Modifier.fillMaxWidth(),
@ -249,6 +252,10 @@ fun NewSpaceSettingsScreen(
modifier = Modifier
.fillMaxWidth()
.animateItem()
.clip(RoundedCornerShape(16.dp))
.clickable {
showTechInfo = true
}
)
}
}
@ -320,6 +327,25 @@ fun NewSpaceSettingsScreen(
)
}
}
if (showTechInfo) {
ModalBottomSheet(
containerColor = colorResource(R.color.background_secondary),
onDismissRequest = {
showTechInfo = false
},
dragHandle = {
Dragger(
modifier = Modifier.padding(vertical = 6.dp)
)
},
content = {
SpaceInfoScreen(
spaceTechInfo = uiState.spaceTechInfo
)
}
)
}
}
@Composable

View file

@ -2,9 +2,11 @@ package com.anytypeio.anytype.ui_settings.space.new_settings
import androidx.compose.runtime.Composable
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.spaces.SpaceIconView
import com.anytypeio.anytype.presentation.spaces.SpaceTechInfo
import com.anytypeio.anytype.presentation.spaces.UiSpaceSettingsItem
import com.anytypeio.anytype.presentation.spaces.UiSpaceSettingsState
@ -44,7 +46,13 @@ fun NewSpaceSettingsScreenPreview() {
UiSpaceSettingsItem.Spacer(height = 32),
),
isEditEnabled = true
isEditEnabled = true,
spaceTechInfo = SpaceTechInfo(
spaceId = SpaceId("space-id"),
createdBy = "Thomas",
creationDateInMillis = null,
networkId = "random network id"
)
),
uiEvent = {},
)

View file

@ -0,0 +1,130 @@
package com.anytypeio.anytype.ui_settings.space.new_settings
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
import com.anytypeio.anytype.core_ui.foundation.Header
import com.anytypeio.anytype.core_ui.views.BodyCalloutRegular
import com.anytypeio.anytype.core_ui.views.PreviewTitle2Regular
import com.anytypeio.anytype.core_utils.clipboard.copyPlainTextToClipboard
import com.anytypeio.anytype.core_utils.const.DateConst
import com.anytypeio.anytype.core_utils.ext.formatTimeInMillis
import com.anytypeio.anytype.presentation.spaces.SpaceTechInfo
import com.anytypeio.anytype.ui_settings.R
@Composable
fun SpaceInfoScreen(
spaceTechInfo: SpaceTechInfo
) {
val context = LocalContext.current
Column(
modifier = Modifier.fillMaxWidth()
) {
Header(
text = stringResource(R.string.space_settings_space_info_button)
)
SpaceInfoItem(
name = stringResource(R.string.space_id),
value = spaceTechInfo.spaceId.id,
onClick = {
context.copyPlainTextToClipboard(
plainText = spaceTechInfo.spaceId.id,
label = "Space ID",
successToast = context.getString(R.string.space_id_copied_toast_msg)
)
}
)
SpaceInfoItem(
name = stringResource(R.string.created_by),
value = spaceTechInfo.createdBy.ifEmpty {
stringResource(id = R.string.unknown)
},
onClick = {
context.copyPlainTextToClipboard(
plainText = spaceTechInfo.createdBy,
label = "Created-by ID",
successToast = context.getString(R.string.created_by_id_copied_toast_msg)
)
}
)
SpaceInfoItem(
name = stringResource(R.string.network_id),
value = spaceTechInfo.networkId.ifEmpty {
stringResource(id = R.string.unknown)
},
onClick = {
context.copyPlainTextToClipboard(
plainText = spaceTechInfo.networkId,
label = "Network ID",
successToast = context.getString(R.string.network_id_copied_toast_msg)
)
}
)
SpaceInfoItem(
name = stringResource(R.string.creation_date),
value = spaceTechInfo.creationDateInMillis?.formatTimeInMillis(
DateConst.DEFAULT_DATE_FORMAT
) ?: stringResource(id = R.string.unknown),
onClick = {
// Do nothing.
}
)
}
}
@Composable
internal fun SpaceInfoItem(
name: String,
value: String,
onClick: () -> Unit
) {
Column(
modifier = Modifier
.clickable {
onClick()
}
.fillMaxWidth()
.padding(
vertical = 12.dp,
horizontal = 20.dp
)
) {
Text(
text = name,
style = BodyCalloutRegular,
color = colorResource(R.color.text_secondary),
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = value,
style = PreviewTitle2Regular,
color = colorResource(R.color.text_primary)
)
}
}
@DefaultPreviews
@Composable
fun SpaceInfoScreenPreview() {
SpaceInfoScreen(
spaceTechInfo = SpaceTechInfo(
spaceId = SpaceId(LoremIpsum(words = 10).toString()),
createdBy = "Walter",
networkId = LoremIpsum(words = 10).toString(),
creationDateInMillis = 21313L
)
)
}

View file

@ -90,6 +90,7 @@ class SpaceSettingsViewModel(
spaceViewContainer.sharedSpaceCount(userPermissionProvider.all()),
activeSpaceMemberSubscriptionContainer.observe(params.space),
) { spaceView, permission, sharedSpaceLimit: Int, sharedSpaceCount: Int, store ->
Timber.d("Got shared space limit: $sharedSpaceLimit, shared space count: $sharedSpaceCount")
val requests: Int = if (store is ActiveSpaceMemberSubscriptionContainer.Store.Data) {
store.members.count { it.status == ParticipantStatus.JOINING }
@ -106,7 +107,18 @@ class SpaceSettingsViewModel(
//todo add logic
val membersNumber = 3
val spaceTechInfo = SpaceTechInfo(
spaceId = params.space,
createdBy = createdBy.orEmpty(),
creationDateInMillis = spaceView
.getValue<Double?>(Relations.CREATED_DATE)
?.let { timeInSeconds -> (timeInSeconds * 1000L).toLong() }
,
networkId = spaceManager.getConfig(params.space)?.network.orEmpty()
)
UiSpaceSettingsState.SpaceSettings(
spaceTechInfo = spaceTechInfo,
items = listOf(
UiSpaceSettingsItem.Icon(
icon = spaceView.spaceIcon(
@ -114,29 +126,27 @@ class SpaceSettingsViewModel(
spaceGradientProvider = gradientProvider
)
),
UiSpaceSettingsItem.Spacer(height = 16),
Spacer(height = 16),
UiSpaceSettingsItem.Name(
//todo support localization for empty space name
name = spaceView.name.orEmpty()
),
UiSpaceSettingsItem.Spacer(height = 12),
Spacer(height = 12),
UiSpaceSettingsItem.Description(
//todo support localization for empty space description
description = spaceView.description.orEmpty()
),
UiSpaceSettingsItem.Spacer(height = 12),
Spacer(height = 12),
UiSpaceSettingsItem.Multiplayer,
UiSpaceSettingsItem.Spacer(height = 8),
Spacer(height = 8),
UiSpaceSettingsItem.Section.Collaboration,
UiSpaceSettingsItem.Members(count = membersNumber),
UiSpaceSettingsItem.Section.Misc,
UiSpaceSettingsItem.SpaceInfo
),
isEditEnabled = permission?.isOwnerOrEditor() == true
)
}.collect { spaceData ->
Timber.d("Space data: ${spaceData}")
uiState.value = spaceData
//spaceViewState.value = spaceData
}.collect { update ->
uiState.value = update
}
}
}

View file

@ -1,12 +1,15 @@
package com.anytypeio.anytype.presentation.spaces
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_models.ext.EMPTY_STRING_VALUE
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.presentation.objects.ObjectIcon
sealed class UiSpaceSettingsState {
data object Initial : UiSpaceSettingsState()
data class SpaceSettings(
val spaceTechInfo: SpaceTechInfo,
val items: List<UiSpaceSettingsItem>,
val isEditEnabled: Boolean
) : UiSpaceSettingsState() {
@ -18,6 +21,13 @@ sealed class UiSpaceSettingsState {
data class SpaceSettingsError(val message: String) : UiSpaceSettingsState()
}
data class SpaceTechInfo(
val spaceId: SpaceId,
val createdBy: String,
val networkId: Id,
val creationDateInMillis: Long?
)
sealed class UiSpaceSettingsItem {
sealed class Section : UiSpaceSettingsItem() {
data object Collaboration : Section()