diff --git a/core-models/src/main/java/com/anytypeio/anytype/core_models/multiplayer/Multiplayer.kt b/core-models/src/main/java/com/anytypeio/anytype/core_models/multiplayer/Multiplayer.kt new file mode 100644 index 0000000000..fad13fecd1 --- /dev/null +++ b/core-models/src/main/java/com/anytypeio/anytype/core_models/multiplayer/Multiplayer.kt @@ -0,0 +1,6 @@ +package com.anytypeio.anytype.core_models.multiplayer + +data class SpaceInviteLink( + val fileKey: String, + val cid: String +) \ No newline at end of file diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/multiplayer/Inviting.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/multiplayer/Inviting.kt new file mode 100644 index 0000000000..020051d4d8 --- /dev/null +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/multiplayer/Inviting.kt @@ -0,0 +1,101 @@ +package com.anytypeio.anytype.core_ui.features.multiplayer + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +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.material3.Card +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.anytypeio.anytype.core_ui.R +import com.anytypeio.anytype.core_ui.foundation.Divider +import com.anytypeio.anytype.core_ui.views.BodyCalloutRegular +import com.anytypeio.anytype.core_ui.views.ButtonPrimary +import com.anytypeio.anytype.core_ui.views.ButtonSize +import com.anytypeio.anytype.core_ui.views.Title1 + +@Composable +@Preview +fun ShareInviteLinkCardPreview() { + ShareInviteLinkCard( + link = "https://anytype.io/ibafyrfhfsag6rea3ifffsasssa3ifffsasssga3ifffsasssga3ifffsas", + onShareInviteClicked = {}, + ) +} + +@Composable +fun ShareInviteLinkCard( + link: String, + onShareInviteClicked: () -> Unit +) { + Card { + Spacer(modifier = Modifier.height(20.dp)) + Row( + modifier = Modifier.padding(horizontal = 20.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = stringResource(R.string.multiplayer_invite_link), + style = Title1, + color = colorResource(id = R.color.text_primary), + modifier = Modifier.weight(1.0f) + ) + Image( + painter = painterResource(id = R.drawable.ic_action_replace), + contentDescription = "Regenerate-invite icon" + ) + } + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = stringResource(R.string.multiplayer_share_invite_link_description), + style = BodyCalloutRegular, + color = colorResource(id = R.color.text_primary), + modifier = Modifier.padding(horizontal = 20.dp) + ) + Spacer(modifier = Modifier.height(8.dp)) + Box( + modifier = Modifier + .padding(horizontal = 20.dp) + .height(48.dp) + .fillMaxWidth(), + contentAlignment = Alignment.CenterStart + ) { + Text( + text = link, + style = BodyCalloutRegular, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + color = colorResource(id = R.color.text_secondary), + modifier = Modifier.fillMaxWidth() + ) + } + Divider() + Spacer(modifier = Modifier.height(16.dp)) + Box( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp) + ) { + ButtonPrimary( + text = stringResource(R.string.multiplayer_share_invite_link), + onClick = onShareInviteClicked, + size = ButtonSize.Large, + modifier = Modifier + .fillMaxWidth() + .height(48.dp) + ) + } + Spacer(modifier = Modifier.height(20.dp)) + } +} \ No newline at end of file diff --git a/core-ui/src/main/res/drawable/ic_action_replace.xml b/core-ui/src/main/res/drawable/ic_action_replace.xml index ed28553cdb..7263dac11c 100644 --- a/core-ui/src/main/res/drawable/ic_action_replace.xml +++ b/core-ui/src/main/res/drawable/ic_action_replace.xml @@ -1,22 +1,10 @@ - - - - - - + diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt index a27c598bdd..fe776ce59d 100644 --- a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt +++ b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt @@ -24,6 +24,7 @@ import com.anytypeio.anytype.core_models.SearchResult import com.anytypeio.anytype.core_models.Struct import com.anytypeio.anytype.core_models.Url import com.anytypeio.anytype.core_models.WidgetLayout +import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteLink import com.anytypeio.anytype.core_models.primitives.SpaceId import com.anytypeio.anytype.data.auth.exception.AnytypeNeedsUpgradeException import com.anytypeio.anytype.data.auth.exception.NotFoundObjectException @@ -898,4 +899,8 @@ class BlockDataRepository( override suspend fun deleteRelationOption(command: Command.DeleteRelationOptions) { return remote.deleteRelationOption(command) } + + override suspend fun generateSpaceInviteLink(space: SpaceId): SpaceInviteLink { + return remote.generateSpaceInviteLink(space) + } } \ No newline at end of file diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt index c4ff67582a..a8eab0a56d 100644 --- a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt +++ b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt @@ -23,6 +23,7 @@ import com.anytypeio.anytype.core_models.SearchResult import com.anytypeio.anytype.core_models.Struct import com.anytypeio.anytype.core_models.Url import com.anytypeio.anytype.core_models.WidgetLayout +import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteLink import com.anytypeio.anytype.core_models.primitives.SpaceId interface BlockRemote { @@ -382,4 +383,6 @@ interface BlockRemote { suspend fun debugStackGoroutines(path: String) suspend fun deleteRelationOption(command: Command.DeleteRelationOptions) + + suspend fun generateSpaceInviteLink(space: SpaceId) : SpaceInviteLink } \ No newline at end of file diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt b/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt index 54c0d8f1f3..8da8a0dd6b 100644 --- a/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt +++ b/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt @@ -24,6 +24,7 @@ import com.anytypeio.anytype.core_models.SearchResult import com.anytypeio.anytype.core_models.Struct import com.anytypeio.anytype.core_models.Url import com.anytypeio.anytype.core_models.WidgetLayout +import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteLink import com.anytypeio.anytype.core_models.primitives.SpaceId import com.anytypeio.anytype.domain.base.Result import com.anytypeio.anytype.domain.block.interactor.sets.CreateObjectSet @@ -429,4 +430,6 @@ interface BlockRepository { suspend fun createTemplateFromObject(ctx: Id): Id suspend fun debugStackGoroutines(path: String) suspend fun deleteRelationOption(command: Command.DeleteRelationOptions) + + suspend fun generateSpaceInviteLink(space: SpaceId) : SpaceInviteLink } \ No newline at end of file diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/multiplayer/GenerateSpaceInviteLink.kt b/domain/src/main/java/com/anytypeio/anytype/domain/multiplayer/GenerateSpaceInviteLink.kt new file mode 100644 index 0000000000..c7dce3fc60 --- /dev/null +++ b/domain/src/main/java/com/anytypeio/anytype/domain/multiplayer/GenerateSpaceInviteLink.kt @@ -0,0 +1,16 @@ +package com.anytypeio.anytype.domain.multiplayer + +import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteLink +import com.anytypeio.anytype.core_models.primitives.SpaceId +import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers +import com.anytypeio.anytype.domain.base.ResultInteractor +import com.anytypeio.anytype.domain.block.repo.BlockRepository + +class GenerateSpaceInviteLink( + private val dispatchers: AppCoroutineDispatchers, + private val repo: BlockRepository +): ResultInteractor(dispatchers.io) { + override suspend fun doWork(params: SpaceId): SpaceInviteLink = repo.generateSpaceInviteLink( + space = params + ) +} \ 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 8bcbccc3a6..5b17290421 100644 --- a/localization/src/main/res/values/strings.xml +++ b/localization/src/main/res/values/strings.xml @@ -1294,9 +1294,15 @@ Tap to provide your network config Current config: %1$s - + + + Share invite link + Send this link to invite others. Assign access rights upon their request approval + Invite link + + \ No newline at end of file diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt index c8df07dd86..dc2bf80e2e 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt @@ -24,6 +24,7 @@ import com.anytypeio.anytype.core_models.SearchResult import com.anytypeio.anytype.core_models.Struct import com.anytypeio.anytype.core_models.Url import com.anytypeio.anytype.core_models.WidgetLayout +import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteLink import com.anytypeio.anytype.core_models.primitives.SpaceId import com.anytypeio.anytype.data.auth.repo.block.BlockRemote import com.anytypeio.anytype.middleware.interactor.Middleware @@ -859,4 +860,8 @@ class BlockMiddleware( override suspend fun deleteRelationOption(command: Command.DeleteRelationOptions) { return middleware.deleteRelationOptions(command) } + + override suspend fun generateSpaceInviteLink(space: SpaceId): SpaceInviteLink { + return middleware.generateSpaceInviteLink(space) + } } \ 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 2969d92037..67e9f8b53a 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 @@ -29,6 +29,7 @@ import com.anytypeio.anytype.core_models.SearchResult import com.anytypeio.anytype.core_models.Struct import com.anytypeio.anytype.core_models.Url import com.anytypeio.anytype.core_models.WidgetLayout +import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteLink import com.anytypeio.anytype.core_models.primitives.SpaceId import com.anytypeio.anytype.core_utils.tools.ThreadInfo import com.anytypeio.anytype.middleware.BuildConfig @@ -2366,6 +2367,21 @@ class Middleware @Inject constructor( if (BuildConfig.DEBUG) logResponse(response) } + @Throws(Exception::class) + fun generateSpaceInviteLink(space: SpaceId) : SpaceInviteLink { + val request = Rpc.Space.InviteGenerate.Request( + spaceId = space.id + ) + if (BuildConfig.DEBUG) logRequest(request) + val response = service.spaceInviteGenerate(request) + if (BuildConfig.DEBUG) logResponse(response) + return SpaceInviteLink( + cid = response.inviteCid, + fileKey= response.inviteFileKey + ) + } + + private fun logRequest(any: Any) { logger.logRequest(any).also { if (BuildConfig.DEBUG && threadInfo.isOnMainThread()) {