mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2966 Chats | Fix | Misc. chat fixes (#1942)
This commit is contained in:
parent
61d705f952
commit
f7406069b1
10 changed files with 143 additions and 81 deletions
|
@ -16,6 +16,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
|
|||
import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
import com.anytypeio.anytype.feature_discussions.presentation.DiscussionViewModel
|
||||
import com.anytypeio.anytype.feature_discussions.presentation.DiscussionViewModelFactory
|
||||
import com.anytypeio.anytype.middleware.EventProxy
|
||||
|
@ -91,4 +92,5 @@ interface DiscussionComponentDependencies : ComponentDependencies {
|
|||
fun logger(): Logger
|
||||
fun members(): ActiveSpaceMemberSubscriptionContainer
|
||||
fun spaceViewSubscriptionContainer(): SpaceViewSubscriptionContainer
|
||||
fun storeOfObjectTypes(): StoreOfObjectTypes
|
||||
}
|
|
@ -161,7 +161,9 @@ class HomeScreenFragment : BaseComposeFragment(),
|
|||
pagerState.animateScrollToPage(1)
|
||||
}
|
||||
},
|
||||
onSpaceIconClicked = vm::onSpaceSettingsClicked
|
||||
onSpaceIconClicked = vm::onSpaceSettingsClicked,
|
||||
membersCount = view?.membersCount ?: 0,
|
||||
name = view?.space?.name.orEmpty()
|
||||
)
|
||||
HorizontalPager(
|
||||
modifier = Modifier
|
||||
|
|
|
@ -9,16 +9,22 @@ import androidx.compose.foundation.layout.height
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
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.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
|
||||
import com.anytypeio.anytype.core_ui.features.SpaceIconView
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
|
||||
import com.anytypeio.anytype.core_ui.views.PreviewTitle2Medium
|
||||
import com.anytypeio.anytype.core_ui.views.Relations3
|
||||
import com.anytypeio.anytype.feature_discussions.R
|
||||
import com.anytypeio.anytype.presentation.spaces.SpaceIconView
|
||||
|
||||
|
@ -28,7 +34,9 @@ fun HomeScreenToolbar(
|
|||
isChatActive: Boolean,
|
||||
onWidgetTabClicked: () -> Unit,
|
||||
onChatTabClicked: () -> Unit,
|
||||
onSpaceIconClicked: () -> Unit
|
||||
onSpaceIconClicked: () -> Unit,
|
||||
name: String,
|
||||
membersCount: Int
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
|
@ -38,11 +46,53 @@ fun HomeScreenToolbar(
|
|||
.padding(horizontal = 20.dp)
|
||||
) {
|
||||
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_home_toolbar_widgets),
|
||||
|
||||
SpaceIconView(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterStart),
|
||||
icon = spaceIconView,
|
||||
onSpaceIconClick = {
|
||||
onSpaceIconClicked()
|
||||
},
|
||||
mainSize = 40.dp
|
||||
)
|
||||
|
||||
Text(
|
||||
text = name.ifEmpty { stringResource(R.string.untitled) },
|
||||
style = PreviewTitle2Medium,
|
||||
color = colorResource(R.color.text_primary),
|
||||
modifier = Modifier.padding(
|
||||
start = 52.dp,
|
||||
top = 13.dp
|
||||
)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = if (membersCount > 0 ) {
|
||||
pluralStringResource(
|
||||
id = R.plurals.multiplayer_number_of_space_members,
|
||||
membersCount,
|
||||
membersCount,
|
||||
membersCount
|
||||
)
|
||||
} else
|
||||
stringResource(id = R.string.three_dots_text_placeholder),
|
||||
style = Relations3,
|
||||
color = colorResource(R.color.text_secondary),
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomStart)
|
||||
.padding(
|
||||
start = 52.dp,
|
||||
bottom = 13.dp
|
||||
)
|
||||
)
|
||||
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_home_toolbar_widgets),
|
||||
modifier = Modifier
|
||||
.padding(end = 48.dp)
|
||||
.size(32.dp)
|
||||
.align(Alignment.CenterStart)
|
||||
.align(Alignment.CenterEnd)
|
||||
.alpha(
|
||||
if (isChatActive) 0.5f else 1f
|
||||
)
|
||||
|
@ -52,15 +102,6 @@ fun HomeScreenToolbar(
|
|||
contentDescription = "Widgets button"
|
||||
)
|
||||
|
||||
SpaceIconView(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
icon = spaceIconView,
|
||||
onSpaceIconClick = {
|
||||
onSpaceIconClicked()
|
||||
},
|
||||
mainSize = 40.dp
|
||||
)
|
||||
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_home_toolbar_chat),
|
||||
modifier = Modifier
|
||||
|
@ -85,6 +126,8 @@ fun HomeScreenToolbarPreview() {
|
|||
onChatTabClicked = {},
|
||||
isChatActive = false,
|
||||
spaceIconView = SpaceIconView.Loading,
|
||||
onSpaceIconClicked = {}
|
||||
onSpaceIconClicked = {},
|
||||
membersCount = 74,
|
||||
name = "Test space"
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
android:viewportWidth="32"
|
||||
android:viewportHeight="32">
|
||||
<path
|
||||
android:pathData="M5,8C5,6.895 5.895,6 7,6H25C26.105,6 27,6.895 27,8C27,9.105 26.105,10 25,10H7C5.895,10 5,9.105 5,8ZM5,24C5,22.895 5.895,22 7,22H25C26.105,22 27,22.895 27,24C27,25.105 26.105,26 25,26H7C5.895,26 5,25.105 5,24ZM7,12C5.895,12 5,12.895 5,14V18C5,19.105 5.895,20 7,20H25C26.105,20 27,19.105 27,18V14C27,12.895 26.105,12 25,12H7Z"
|
||||
android:pathData="M8,6C6.895,6 6,6.895 6,8V12.889C6,13.993 6.895,14.889 8,14.889H12.889C13.993,14.889 14.889,13.993 14.889,12.889V8C14.889,6.895 13.993,6 12.889,6H8ZM19.111,6C18.006,6 17.111,6.895 17.111,8V12.889C17.111,13.993 18.006,14.889 19.111,14.889H24C25.104,14.889 26,13.993 26,12.889V8C26,6.895 25.104,6 24,6H19.111ZM6,19.111C6,18.006 6.895,17.111 8,17.111H12.889C13.993,17.111 14.889,18.006 14.889,19.111V24C14.889,25.104 13.993,26 12.889,26H8C6.895,26 6,25.104 6,24V19.111ZM19.111,17.111C18.006,17.111 17.111,18.006 17.111,19.111V24C17.111,25.104 18.006,26 19.111,26H24C25.104,26 26,25.104 26,24V19.111C26,18.006 25.104,17.111 24,17.111H19.111Z"
|
||||
android:fillColor="@color/glyph_button"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
|
|
|
@ -51,7 +51,8 @@ sealed interface DiscussionView {
|
|||
data class Link(
|
||||
val target: Id,
|
||||
val wrapper: ObjectWrapper.Basic?,
|
||||
val icon: ObjectIcon = ObjectIcon.None
|
||||
val icon: ObjectIcon = ObjectIcon.None,
|
||||
val typeName: String
|
||||
): Attachment()
|
||||
}
|
||||
|
||||
|
|
|
@ -28,12 +28,14 @@ import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionCon
|
|||
import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.`object`.OpenObject
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
import com.anytypeio.anytype.presentation.common.BaseViewModel
|
||||
import com.anytypeio.anytype.presentation.home.OpenObjectNavigation
|
||||
import com.anytypeio.anytype.presentation.home.navigation
|
||||
import com.anytypeio.anytype.presentation.mapper.objectIcon
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.search.GlobalSearchItemView
|
||||
import java.sql.Types
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
|
@ -58,7 +60,8 @@ class DiscussionViewModel @Inject constructor(
|
|||
private val urlBuilder: UrlBuilder,
|
||||
private val spaceViews: SpaceViewSubscriptionContainer,
|
||||
private val dispatchers: AppCoroutineDispatchers,
|
||||
private val uploadFile: UploadFile
|
||||
private val uploadFile: UploadFile,
|
||||
private val storeOfObjectTypes: StoreOfObjectTypes
|
||||
) : BaseViewModel() {
|
||||
|
||||
val name = MutableStateFlow<String?>(null)
|
||||
|
@ -192,7 +195,6 @@ class DiscussionViewModel @Inject constructor(
|
|||
target = attachment.target,
|
||||
url = urlBuilder.medium(path = attachment.target)
|
||||
)
|
||||
|
||||
else -> {
|
||||
val wrapper = dependencies[attachment.target]
|
||||
if (wrapper?.layout == ObjectType.Layout.IMAGE) {
|
||||
|
@ -201,10 +203,15 @@ class DiscussionViewModel @Inject constructor(
|
|||
url = urlBuilder.large(path = attachment.target)
|
||||
)
|
||||
} else {
|
||||
val type = wrapper?.type?.firstOrNull()
|
||||
DiscussionView.Message.Attachment.Link(
|
||||
target = attachment.target,
|
||||
wrapper = wrapper,
|
||||
icon = wrapper?.objectIcon(urlBuilder) ?: ObjectIcon.None
|
||||
icon = wrapper?.objectIcon(urlBuilder) ?: ObjectIcon.None,
|
||||
typeName = if (type != null)
|
||||
storeOfObjectTypes.get(type)?.name.orEmpty()
|
||||
else
|
||||
""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionCon
|
|||
import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.`object`.OpenObject
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
import com.anytypeio.anytype.presentation.common.BaseViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -33,7 +34,8 @@ class DiscussionViewModelFactory @Inject constructor(
|
|||
private val urlBuilder: UrlBuilder,
|
||||
private val spaceViews: SpaceViewSubscriptionContainer,
|
||||
private val dispatchers: AppCoroutineDispatchers,
|
||||
private val uploadFile: UploadFile
|
||||
private val uploadFile: UploadFile,
|
||||
private val storeOfObjectTypes: StoreOfObjectTypes
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T = DiscussionViewModel(
|
||||
|
@ -50,6 +52,7 @@ class DiscussionViewModelFactory @Inject constructor(
|
|||
editChatMessage = editChatMessage,
|
||||
spaceViews = spaceViews,
|
||||
dispatchers = dispatchers,
|
||||
uploadFile = uploadFile
|
||||
uploadFile = uploadFile,
|
||||
storeOfObjectTypes = storeOfObjectTypes
|
||||
) as T
|
||||
}
|
|
@ -202,7 +202,8 @@ fun BubbleWithAttachmentPreview() {
|
|||
add(
|
||||
DiscussionView.Message.Attachment.Link(
|
||||
target = "ID",
|
||||
wrapper = null
|
||||
wrapper = null,
|
||||
typeName = "Page"
|
||||
)
|
||||
)
|
||||
},
|
||||
|
|
|
@ -977,11 +977,6 @@ fun Messages(
|
|||
)
|
||||
if (msg.isUserAuthor) {
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
ChatUserAvatar(
|
||||
msg = msg,
|
||||
avatar = msg.avatar,
|
||||
modifier = Modifier.align(Alignment.Bottom)
|
||||
)
|
||||
} else {
|
||||
Spacer(modifier = Modifier.width(40.dp))
|
||||
}
|
||||
|
@ -1084,9 +1079,6 @@ private fun ChatUserAvatar(
|
|||
}
|
||||
}
|
||||
|
||||
val defaultBubbleColor = Color(0x99FFFFFF)
|
||||
val userMessageBubbleColor = Color(0x66000000)
|
||||
|
||||
@OptIn(ExperimentalGlideComposeApi::class)
|
||||
@Composable
|
||||
fun Bubble(
|
||||
|
@ -1114,9 +1106,9 @@ fun Bubble(
|
|||
.fillMaxWidth()
|
||||
.background(
|
||||
color = if (isUserAuthor)
|
||||
userMessageBubbleColor
|
||||
colorResource(R.color.navigation_panel_icon)
|
||||
else
|
||||
defaultBubbleColor,
|
||||
colorResource(R.color.navigation_panel),
|
||||
shape = RoundedCornerShape(20.dp)
|
||||
)
|
||||
.clip(RoundedCornerShape(20.dp))
|
||||
|
@ -1250,41 +1242,7 @@ fun Bubble(
|
|||
else
|
||||
colorResource(id = R.color.text_primary),
|
||||
)
|
||||
attachments.forEach { attachment ->
|
||||
when(attachment) {
|
||||
is DiscussionView.Message.Attachment.Image -> {
|
||||
GlideImage(
|
||||
model = attachment.url,
|
||||
contentDescription = "Attachment image",
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.fillMaxWidth()
|
||||
.clip(shape = RoundedCornerShape(16.dp))
|
||||
.clickable {
|
||||
onAttachmentClicked(attachment)
|
||||
}
|
||||
)
|
||||
}
|
||||
is DiscussionView.Message.Attachment.Link -> {
|
||||
AttachedObject(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
top = 8.dp
|
||||
)
|
||||
.fillMaxWidth()
|
||||
,
|
||||
title = attachment.wrapper?.name.orEmpty(),
|
||||
type = attachment.wrapper?.type?.firstOrNull().orEmpty(),
|
||||
icon = attachment.icon,
|
||||
onAttachmentClicked = {
|
||||
onAttachmentClicked(attachment)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
BubbleAttachments(attachments, onAttachmentClicked)
|
||||
if (reactions.isNotEmpty()) {
|
||||
ReactionList(
|
||||
reactions = reactions,
|
||||
|
@ -1369,18 +1327,20 @@ fun Bubble(
|
|||
showDropdownMenu = false
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
text = stringResource(R.string.copy),
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
onCopyMessage()
|
||||
showDropdownMenu = false
|
||||
}
|
||||
)
|
||||
if (content.msg.isNotEmpty()) {
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
text = stringResource(R.string.copy),
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
onCopyMessage()
|
||||
showDropdownMenu = false
|
||||
}
|
||||
)
|
||||
}
|
||||
if (isUserAuthor) {
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
|
@ -1414,6 +1374,49 @@ fun Bubble(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalGlideComposeApi::class)
|
||||
private fun BubbleAttachments(
|
||||
attachments: List<DiscussionView.Message.Attachment>,
|
||||
onAttachmentClicked: (DiscussionView.Message.Attachment) -> Unit
|
||||
) {
|
||||
attachments.forEach { attachment ->
|
||||
when (attachment) {
|
||||
is DiscussionView.Message.Attachment.Image -> {
|
||||
GlideImage(
|
||||
model = attachment.url,
|
||||
contentDescription = "Attachment image",
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.fillMaxWidth()
|
||||
.clip(shape = RoundedCornerShape(16.dp))
|
||||
.clickable {
|
||||
onAttachmentClicked(attachment)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
is DiscussionView.Message.Attachment.Link -> {
|
||||
AttachedObject(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
top = 8.dp
|
||||
)
|
||||
.fillMaxWidth(),
|
||||
title = attachment.wrapper?.name.orEmpty(),
|
||||
type = attachment.typeName,
|
||||
icon = attachment.icon,
|
||||
onAttachmentClicked = {
|
||||
onAttachmentClicked(attachment)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TopDiscussionToolbar(
|
||||
title: String? = null,
|
||||
|
|
|
@ -19,7 +19,7 @@ appcompatVersion = '1.7.0'
|
|||
fragmentVersion = "1.8.5"
|
||||
exoplayerVersion = "2.19.1"
|
||||
wireVersion = "4.9.8"
|
||||
glideVersion = "4.14.2"
|
||||
glideVersion = "4.16.0"
|
||||
glideComposeVersion = "1.0.0-beta01"
|
||||
mockitoKotlinVersion = "5.3.1"
|
||||
junitVersion = '4.13.2'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue