mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
Droid 2176 Multiplayer | Fix | Design and wording fixes (#1110)
This commit is contained in:
parent
c8dfe2ced0
commit
12c9f26d9c
7 changed files with 144 additions and 100 deletions
|
@ -17,10 +17,10 @@ import com.anytypeio.anytype.core_models.Id
|
|||
import com.anytypeio.anytype.core_models.ext.EMPTY_STRING_VALUE
|
||||
import com.anytypeio.anytype.core_ui.features.multiplayer.JoinSpaceScreen
|
||||
import com.anytypeio.anytype.core_ui.foundation.AlertConfig
|
||||
import com.anytypeio.anytype.core_ui.foundation.Announcement
|
||||
import com.anytypeio.anytype.core_ui.foundation.BUTTON_SECONDARY
|
||||
import com.anytypeio.anytype.core_ui.foundation.GRADIENT_TYPE_BLUE
|
||||
import com.anytypeio.anytype.core_ui.foundation.GenericAlert
|
||||
import com.anytypeio.anytype.core_ui.foundation.Warning
|
||||
import com.anytypeio.anytype.core_utils.ext.arg
|
||||
import com.anytypeio.anytype.core_utils.ext.toast
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
|
||||
|
@ -50,29 +50,41 @@ class RequestJoinSpaceFragment : BaseBottomSheetComposeFragment() {
|
|||
setContent {
|
||||
MaterialTheme(typography = typography) {
|
||||
when(val state = vm.state.collectAsStateWithLifecycle().value) {
|
||||
is TypedViewState.Loading -> {
|
||||
// Render nothing.
|
||||
}
|
||||
is TypedViewState.Success -> {
|
||||
is TypedViewState.Loading, is TypedViewState.Success -> {
|
||||
val isLoading: Boolean
|
||||
val spaceName: String
|
||||
val createdByName: String
|
||||
if (state is TypedViewState.Loading) {
|
||||
isLoading = true
|
||||
spaceName = stringResource(R.string.three_dots_text_placeholder)
|
||||
createdByName = stringResource(R.string.three_dots_text_placeholder)
|
||||
}
|
||||
else {
|
||||
isLoading = vm.isRequestInProgress.collectAsStateWithLifecycle().value
|
||||
with(state as TypedViewState.Success) {
|
||||
spaceName = state.data.spaceName
|
||||
createdByName = state.data.creatorName
|
||||
}
|
||||
}
|
||||
JoinSpaceScreen(
|
||||
isLoading = vm.isRequestInProgress.collectAsStateWithLifecycle().value,
|
||||
isLoading = isLoading,
|
||||
onRequestJoinSpaceClicked = vm::onRequestToJoinClicked,
|
||||
spaceName = state.data.spaceName,
|
||||
createdByName = state.data.creatorName
|
||||
spaceName = spaceName,
|
||||
createdByName = createdByName
|
||||
)
|
||||
}
|
||||
is TypedViewState.Error -> {
|
||||
when(val err = state.error) {
|
||||
is ErrorView.AlreadySpaceMember -> {
|
||||
Warning(
|
||||
Announcement(
|
||||
title = stringResource(id = R.string.multiplayer_already_space_member),
|
||||
subtitle = EMPTY_STRING_VALUE,
|
||||
actionButtonText = stringResource(id = R.string.multiplayer_open_space),
|
||||
cancelButtonText = stringResource(id = R.string.cancel),
|
||||
onNegativeClick = {
|
||||
onLeftClicked = {
|
||||
dismiss()
|
||||
},
|
||||
onPositiveClick = {
|
||||
onRightClicked = {
|
||||
vm.onOpenSpaceClicked(err.space)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -161,6 +161,15 @@ private fun SelectSpaceSpaceItem(
|
|||
gradientBackground = colorResource(id = R.color.default_gradient_background),
|
||||
gradientCornerRadius = 4.dp
|
||||
)
|
||||
if (item.view.isShared) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_shared_space_arrow),
|
||||
contentDescription = "Shared space arrow icon",
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomStart)
|
||||
.padding(start = 8.dp, bottom = 8.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
Text(
|
||||
|
|
|
@ -14,8 +14,6 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
|
@ -25,7 +23,6 @@ import androidx.compose.ui.draw.alpha
|
|||
import androidx.compose.ui.graphics.Color
|
||||
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 androidx.compose.ui.unit.dp
|
||||
|
@ -281,77 +278,70 @@ fun Warning(
|
|||
}
|
||||
}
|
||||
|
||||
@ExperimentalMaterialApi
|
||||
@Composable
|
||||
fun Announcement(
|
||||
title: String,
|
||||
subtitle: String,
|
||||
onBackClicked: () -> Unit,
|
||||
onNextClicked: () -> Unit
|
||||
actionButtonText: String,
|
||||
cancelButtonText: String,
|
||||
onRightClicked: () -> Unit,
|
||||
onLeftClicked: () -> Unit,
|
||||
) {
|
||||
Box(contentAlignment = Alignment.BottomCenter) {
|
||||
Card(
|
||||
Column {
|
||||
Text(
|
||||
text = title,
|
||||
modifier = Modifier.padding(
|
||||
top = 24.dp,
|
||||
start = 20.dp,
|
||||
end = 20.dp,
|
||||
bottom = 16.dp
|
||||
end = 20.dp
|
||||
),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
backgroundColor = colorResource(R.color.background_secondary)
|
||||
) {
|
||||
Column {
|
||||
Text(
|
||||
text = title,
|
||||
modifier = Modifier.padding(
|
||||
top = 24.dp,
|
||||
start = 20.dp,
|
||||
end = 20.dp
|
||||
),
|
||||
style = HeadlineHeading,
|
||||
color = colorResource(R.color.text_primary)
|
||||
)
|
||||
Text(
|
||||
text = subtitle,
|
||||
modifier = Modifier.padding(
|
||||
top = 12.dp,
|
||||
start = 20.dp,
|
||||
end = 20.dp
|
||||
),
|
||||
style = BodyCalloutRegular,
|
||||
color = colorResource(R.color.text_primary)
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.height(68.dp)
|
||||
.padding(
|
||||
top = 8.dp,
|
||||
start = 20.dp,
|
||||
end = 20.dp
|
||||
)
|
||||
.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
ButtonSecondary(
|
||||
text = stringResource(R.string.back),
|
||||
onClick = onBackClicked,
|
||||
size = ButtonSize.LargeSecondary,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1.0f)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(10.dp))
|
||||
ButtonPrimary(
|
||||
text = stringResource(R.string.next),
|
||||
onClick = onNextClicked,
|
||||
size = ButtonSize.Large,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1.0f)
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
}
|
||||
style = HeadlineHeading,
|
||||
color = colorResource(R.color.text_primary)
|
||||
)
|
||||
if (subtitle.isNotEmpty()) {
|
||||
Text(
|
||||
text = subtitle,
|
||||
modifier = Modifier.padding(
|
||||
top = 12.dp,
|
||||
start = 20.dp,
|
||||
end = 20.dp,
|
||||
bottom = 10.dp
|
||||
),
|
||||
style = BodyCalloutRegular,
|
||||
color = colorResource(R.color.text_primary)
|
||||
)
|
||||
} else {
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
top = 10.dp,
|
||||
start = 20.dp,
|
||||
end = 20.dp
|
||||
)
|
||||
.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
ButtonSecondary(
|
||||
onClick = onLeftClicked,
|
||||
size = ButtonSize.LargeSecondary,
|
||||
text = cancelButtonText,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(10.dp))
|
||||
ButtonPrimary(
|
||||
onClick = onRightClicked,
|
||||
size = ButtonSize.Large,
|
||||
text = actionButtonText,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f)
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -376,4 +366,17 @@ fun WarningPreview() {
|
|||
onNegativeClick = {},
|
||||
onPositiveClick = {}
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun AnnouncementPreview() {
|
||||
Announcement(
|
||||
title = "Leave space",
|
||||
subtitle = "Investors space will be removed from your devices and you will no longer have access to it",
|
||||
actionButtonText = "Leave space",
|
||||
cancelButtonText = "Cancel",
|
||||
onLeftClicked = {},
|
||||
onRightClicked = {}
|
||||
)
|
||||
}
|
13
core-ui/src/main/res/drawable/ic_shared_space_arrow.xml
Normal file
13
core-ui/src/main/res/drawable/ic_shared_space_arrow.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16">
|
||||
<path
|
||||
android:pathData="M8,0L8,0A8,8 0,0 1,16 8L16,8A8,8 0,0 1,8 16L8,16A8,8 0,0 1,0 8L0,8A8,8 0,0 1,8 0z"
|
||||
android:fillColor="#B3252525"
|
||||
android:fillAlpha="0.7"/>
|
||||
<path
|
||||
android:pathData="M11.711,10.754L10.607,10.761L10.607,6.188L4.685,12.11L3.892,11.316L9.814,5.394L5.248,5.401V4.29L11.711,4.29L11.711,10.754Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
|
@ -1346,7 +1346,7 @@
|
|||
<string name="multiplayer_show_qr_code">Show QR code</string>
|
||||
<string name="multiplayer_how_to_share_space">How to share a space?</string>
|
||||
<string name="multiplayer_how_to_share_space_step_1">Please provide the link to the person you\'d like to collaborate with.</string>
|
||||
<string name="multiplayer_how_to_share_space_qr_code">Please provide this QR code to the person you\'d like to collaborate with.</string>
|
||||
<string name="multiplayer_how_to_share_space_qr_code">Show this QR code to the person you\'d like to collaborate with.</string>
|
||||
<string name="multiplayer_how_to_share_space_step_2">By clicking the link, a person requests to join the space.</string>
|
||||
<string name="multiplayer_how_to_share_space_step_3">After approving the request, you can choose the access rights for that person.</string>
|
||||
<string name="multiplayer_delete_space_sharing_link">Delete sharing link</string>
|
||||
|
@ -1487,4 +1487,7 @@
|
|||
<string name="gallery_experience_alert_button_space">Open space</string>
|
||||
<string name="gallery_experience_alert_button_error">Close</string>
|
||||
|
||||
|
||||
<string name="three_dots_text_placeholder">...</string>
|
||||
|
||||
</resources>
|
|
@ -14,6 +14,7 @@ import com.anytypeio.anytype.core_models.Id
|
|||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceAccessType
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_models.restrictions.SpaceStatus
|
||||
import com.anytypeio.anytype.core_utils.ext.allUniqueBy
|
||||
|
@ -42,7 +43,7 @@ import kotlinx.coroutines.launch
|
|||
import timber.log.Timber
|
||||
|
||||
class SelectSpaceViewModel(
|
||||
private val storelessSubscriptionContainer: StorelessSubscriptionContainer,
|
||||
private val container: StorelessSubscriptionContainer,
|
||||
private val spaceManager: SpaceManager,
|
||||
private val spaceGradientProvider: SpaceGradientProvider,
|
||||
private val urlBuilder: UrlBuilder,
|
||||
|
@ -57,7 +58,7 @@ class SelectSpaceViewModel(
|
|||
private val profile = spaceManager
|
||||
.observe()
|
||||
.flatMapLatest { config ->
|
||||
storelessSubscriptionContainer.subscribe(
|
||||
container.subscribe(
|
||||
StoreSearchByIdsParams(
|
||||
subscription = SELECT_SPACE_PROFILE_SUBSCRIPTION,
|
||||
keys = listOf(
|
||||
|
@ -82,7 +83,7 @@ class SelectSpaceViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private val spaces: Flow<List<ObjectWrapper.Basic>> = storelessSubscriptionContainer.subscribe(
|
||||
private val spaces: Flow<List<ObjectWrapper.SpaceView>> = container.subscribe(
|
||||
StoreSearchParams(
|
||||
subscription = SELECT_SPACE_SUBSCRIPTION,
|
||||
keys = listOf(
|
||||
|
@ -92,7 +93,8 @@ class SelectSpaceViewModel(
|
|||
Relations.ICON_IMAGE,
|
||||
Relations.ICON_EMOJI,
|
||||
Relations.ICON_OPTION,
|
||||
Relations.SPACE_ACCOUNT_STATUS
|
||||
Relations.SPACE_ACCOUNT_STATUS,
|
||||
Relations.SPACE_ACCESS_TYPE
|
||||
),
|
||||
filters = listOf(
|
||||
DVFilter(
|
||||
|
@ -131,7 +133,9 @@ class SelectSpaceViewModel(
|
|||
"There were duplicated objects. Need to investigate this issue"
|
||||
}
|
||||
}
|
||||
spaces.distinctBy { it.id }
|
||||
spaces.distinctBy { it.id }.map { obj ->
|
||||
ObjectWrapper.SpaceView(obj.map)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildUI() {
|
||||
|
@ -160,7 +164,8 @@ class SelectSpaceViewModel(
|
|||
icon = wrapper.spaceIcon(
|
||||
builder = urlBuilder,
|
||||
spaceGradientProvider = spaceGradientProvider
|
||||
)
|
||||
),
|
||||
isShared = wrapper.spaceAccessType == SpaceAccessType.SHARED
|
||||
)
|
||||
)
|
||||
} else {
|
||||
|
@ -239,7 +244,7 @@ class SelectSpaceViewModel(
|
|||
|
||||
private fun proceedWithUnsubscribing() {
|
||||
viewModelScope.launch {
|
||||
storelessSubscriptionContainer.unsubscribe(
|
||||
container.unsubscribe(
|
||||
subscriptions = listOf(
|
||||
SELECT_SPACE_PROFILE_SUBSCRIPTION,
|
||||
SELECT_SPACE_SUBSCRIPTION
|
||||
|
@ -260,7 +265,7 @@ class SelectSpaceViewModel(
|
|||
override fun <T : ViewModel> create(
|
||||
modelClass: Class<T>
|
||||
) = SelectSpaceViewModel(
|
||||
storelessSubscriptionContainer = storelessSubscriptionContainer,
|
||||
container = storelessSubscriptionContainer,
|
||||
spaceManager = spaceManager,
|
||||
spaceGradientProvider = spaceGradientProvider,
|
||||
urlBuilder = urlBuilder,
|
||||
|
@ -282,7 +287,8 @@ data class WorkspaceView(
|
|||
val space: Id,
|
||||
val name: String?,
|
||||
val isSelected: Boolean = false,
|
||||
val icon: SpaceIconView
|
||||
val isShared: Boolean,
|
||||
val icon: SpaceIconView,
|
||||
)
|
||||
|
||||
sealed class SelectSpaceView {
|
||||
|
|
|
@ -350,6 +350,11 @@ fun PrivateSpaceSharing(
|
|||
modifier = Modifier
|
||||
.height(52.dp)
|
||||
.fillMaxWidth()
|
||||
.noRippleClickable(
|
||||
onClick = throttledClick(
|
||||
onClick = { onSharePrivateSpaceClicked() }
|
||||
)
|
||||
)
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
|
@ -360,13 +365,7 @@ fun PrivateSpaceSharing(
|
|||
style = BodyRegular
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterEnd)
|
||||
.noRippleClickable(
|
||||
onClick = throttledClick(
|
||||
onClick = { onSharePrivateSpaceClicked() }
|
||||
)
|
||||
)
|
||||
modifier = Modifier.align(Alignment.CenterEnd)
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.align(Alignment.CenterVertically),
|
||||
|
@ -395,6 +394,11 @@ fun SharedSpaceSharing(
|
|||
modifier = Modifier
|
||||
.height(52.dp)
|
||||
.fillMaxWidth()
|
||||
.noRippleClickable(
|
||||
onClick = throttledClick(
|
||||
onClick = { onManageSharedSpaceClicked() }
|
||||
)
|
||||
)
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
|
@ -405,13 +409,7 @@ fun SharedSpaceSharing(
|
|||
style = BodyRegular
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterEnd)
|
||||
.noRippleClickable(
|
||||
onClick = throttledClick(
|
||||
onClick = { onManageSharedSpaceClicked() }
|
||||
)
|
||||
)
|
||||
modifier = Modifier.align(Alignment.CenterEnd)
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.align(Alignment.CenterVertically),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue