mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
Droid 3622 add counters to space chat widget (#2449)
This commit is contained in:
parent
5fe1d8489d
commit
622b4ea27c
15 changed files with 249 additions and 103 deletions
|
@ -11,6 +11,7 @@ import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
|||
import com.anytypeio.anytype.domain.bin.EmptyBin
|
||||
import com.anytypeio.anytype.domain.block.interactor.Move
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.domain.chats.ChatPreviewContainer
|
||||
import com.anytypeio.anytype.domain.config.ConfigStorage
|
||||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
import com.anytypeio.anytype.domain.debugging.Logger
|
||||
|
@ -300,4 +301,5 @@ interface HomeScreenDependencies : ComponentDependencies {
|
|||
fun featureToggles(): FeatureToggles
|
||||
fun payloadDelegator(): PayloadDelegator
|
||||
fun fieldParser(): FieldParser
|
||||
fun chatPreviews(): ChatPreviewContainer
|
||||
}
|
|
@ -229,7 +229,8 @@ object SubscriptionsModule {
|
|||
isSpaceDeleted: SpaceDeletedStatusWatcher,
|
||||
profileSubscriptionManager: ProfileSubscriptionManager,
|
||||
networkConnectionStatus: NetworkConnectionStatus,
|
||||
deviceTokenStoringService: DeviceTokenStoringService
|
||||
deviceTokenStoringService: DeviceTokenStoringService,
|
||||
chatPreviewContainer: ChatPreviewContainer
|
||||
): GlobalSubscriptionManager = GlobalSubscriptionManager.Default(
|
||||
types = types,
|
||||
relations = relations,
|
||||
|
@ -237,7 +238,8 @@ object SubscriptionsModule {
|
|||
isSpaceDeleted = isSpaceDeleted,
|
||||
profile = profileSubscriptionManager,
|
||||
networkConnectionStatus = networkConnectionStatus,
|
||||
deviceTokenStoringService = deviceTokenStoringService
|
||||
deviceTokenStoringService = deviceTokenStoringService,
|
||||
chatPreviewContainer = chatPreviewContainer
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
|
|
@ -499,7 +499,9 @@ private fun WidgetList(
|
|||
is WidgetView.SpaceChat -> {
|
||||
SpaceChatWidgetCard(
|
||||
mode = mode,
|
||||
onWidgetClicked = { onBundledWidgetHeaderClicked(item.id) }
|
||||
unReadMentionCount = item.unreadMentionCount,
|
||||
unReadMessageCount = item.unreadMessageCount,
|
||||
onWidgetClicked = { onWidgetSourceClicked(item.id, item.source) }
|
||||
)
|
||||
}
|
||||
is WidgetView.Action.EditWidgets -> {
|
||||
|
|
|
@ -6,9 +6,15 @@ import androidx.compose.foundation.Image
|
|||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
@ -17,19 +23,24 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.draw.clip
|
||||
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.R
|
||||
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
|
||||
import com.anytypeio.anytype.core_ui.views.Caption1Regular
|
||||
import com.anytypeio.anytype.core_ui.views.HeadlineSubheading
|
||||
import com.anytypeio.anytype.presentation.home.InteractionMode
|
||||
|
||||
@Composable
|
||||
fun SpaceChatWidgetCard(
|
||||
mode: InteractionMode,
|
||||
onWidgetClicked: () -> Unit = {}
|
||||
onWidgetClicked: () -> Unit = {},
|
||||
unReadMessageCount: Int = 0,
|
||||
unReadMentionCount: Int = 0
|
||||
) {
|
||||
Box(
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(start = 20.dp, end = 20.dp, top = 6.dp, bottom = 6.dp)
|
||||
.fillMaxWidth()
|
||||
|
@ -47,45 +58,76 @@ fun SpaceChatWidgetCard(
|
|||
} else {
|
||||
Modifier
|
||||
}
|
||||
)
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_widget_all_content),
|
||||
painter = painterResource(id = R.drawable.ic_widget_chat),
|
||||
contentDescription = "All content icon",
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterStart)
|
||||
.padding(start = 16.dp)
|
||||
)
|
||||
|
||||
Text(
|
||||
// Temporary hard-coded name for the widget
|
||||
text = "Space chat",
|
||||
text = stringResource(R.string.chat),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterStart)
|
||||
.padding(start = 44.dp, end = 16.dp),
|
||||
.weight(1f)
|
||||
.padding(start = 8.dp, end = 16.dp),
|
||||
style = HeadlineSubheading,
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
)
|
||||
|
||||
if (unReadMentionCount > 0) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(
|
||||
color = colorResource(R.color.transparent_active),
|
||||
shape = CircleShape
|
||||
)
|
||||
.size(20.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.ic_chat_widget_mention),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (unReadMessageCount > 0) {
|
||||
if (unReadMentionCount > 0) {
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(20.dp)
|
||||
.defaultMinSize(minWidth = 20.dp)
|
||||
.background(
|
||||
color = colorResource(R.color.transparent_active),
|
||||
shape = CircleShape
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = unReadMentionCount.toString(),
|
||||
style = Caption1Regular,
|
||||
color = colorResource(id = R.color.text_white),
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.width(16.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(
|
||||
name = "Dark Mode",
|
||||
showBackground = true,
|
||||
uiMode = UI_MODE_NIGHT_YES
|
||||
)
|
||||
@Preview(
|
||||
name = "Light Mode",
|
||||
showBackground = true,
|
||||
uiMode = UI_MODE_NIGHT_NO
|
||||
)
|
||||
@DefaultPreviews
|
||||
@Composable
|
||||
fun SpaceChatWidgetPreview() {
|
||||
SpaceChatWidgetCard(
|
||||
onWidgetClicked = {},
|
||||
mode = InteractionMode.Default
|
||||
mode = InteractionMode.Default,
|
||||
unReadMessageCount = 1,
|
||||
unReadMentionCount = 1
|
||||
)
|
||||
}
|
||||
|
|
9
core-ui/src/main/res/drawable/ic_chat_widget_mention.xml
Normal file
9
core-ui/src/main/res/drawable/ic_chat_widget_mention.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="12dp"
|
||||
android:height="12dp"
|
||||
android:viewportWidth="12"
|
||||
android:viewportHeight="12">
|
||||
<path
|
||||
android:pathData="M6.366,11.887C5.409,11.887 4.564,11.756 3.83,11.494C3.095,11.234 2.478,10.851 1.978,10.345C1.478,9.839 1.1,9.219 0.844,8.484C0.588,7.75 0.459,6.909 0.459,5.962C0.459,5.047 0.589,4.228 0.849,3.506C1.111,2.784 1.491,2.172 1.988,1.669C2.488,1.162 3.094,0.776 3.806,0.511C4.522,0.245 5.331,0.112 6.234,0.112C7.113,0.112 7.881,0.256 8.541,0.544C9.203,0.828 9.756,1.214 10.2,1.701C10.647,2.186 10.981,2.731 11.203,3.337C11.428,3.944 11.541,4.569 11.541,5.212C11.541,5.665 11.519,6.125 11.475,6.59C11.431,7.056 11.339,7.484 11.198,7.875C11.058,8.262 10.841,8.575 10.547,8.812C10.256,9.05 9.863,9.169 9.366,9.169C9.147,9.169 8.906,9.134 8.644,9.065C8.381,8.997 8.149,8.883 7.945,8.723C7.742,8.564 7.622,8.35 7.584,8.081H7.528C7.453,8.262 7.338,8.434 7.181,8.597C7.028,8.759 6.827,8.889 6.577,8.986C6.33,9.083 6.028,9.125 5.672,9.112C5.266,9.097 4.908,9.006 4.599,8.84C4.289,8.672 4.03,8.444 3.82,8.156C3.614,7.865 3.458,7.529 3.352,7.148C3.249,6.764 3.197,6.35 3.197,5.906C3.197,5.484 3.259,5.098 3.384,4.748C3.509,4.398 3.683,4.092 3.905,3.829C4.13,3.567 4.392,3.358 4.692,3.201C4.995,3.042 5.322,2.944 5.672,2.906C5.984,2.875 6.269,2.889 6.525,2.948C6.781,3.004 6.992,3.09 7.158,3.206C7.324,3.319 7.428,3.444 7.472,3.581H7.528V3.056H8.522V7.294C8.522,7.556 8.595,7.787 8.742,7.987C8.889,8.187 9.103,8.287 9.384,8.287C9.703,8.287 9.947,8.178 10.116,7.959C10.288,7.74 10.405,7.403 10.467,6.947C10.533,6.49 10.566,5.906 10.566,5.194C10.566,4.775 10.508,4.362 10.392,3.956C10.28,3.547 10.108,3.164 9.877,2.808C9.649,2.451 9.359,2.137 9.009,1.865C8.659,1.594 8.249,1.381 7.777,1.228C7.308,1.072 6.775,0.994 6.178,0.994C5.444,0.994 4.786,1.108 4.205,1.336C3.627,1.561 3.134,1.89 2.728,2.325C2.325,2.756 2.017,3.281 1.805,3.9C1.595,4.515 1.491,5.215 1.491,6C1.491,6.797 1.595,7.504 1.805,8.123C2.017,8.742 2.33,9.264 2.742,9.689C3.158,10.114 3.672,10.436 4.284,10.655C4.897,10.876 5.603,10.987 6.403,10.987C6.747,10.987 7.086,10.955 7.42,10.889C7.755,10.823 8.05,10.751 8.306,10.673C8.563,10.595 8.747,10.537 8.859,10.5L9.122,11.362C8.928,11.444 8.675,11.525 8.363,11.606C8.053,11.687 7.722,11.755 7.369,11.808C7.019,11.861 6.684,11.887 6.366,11.887ZM5.822,8.156C6.241,8.156 6.58,8.072 6.839,7.903C7.099,7.734 7.288,7.479 7.406,7.139C7.525,6.798 7.584,6.369 7.584,5.85C7.584,5.325 7.519,4.915 7.388,4.622C7.256,4.328 7.063,4.122 6.806,4.003C6.55,3.884 6.234,3.825 5.859,3.825C5.503,3.825 5.199,3.919 4.945,4.106C4.695,4.29 4.503,4.537 4.369,4.847C4.238,5.153 4.172,5.487 4.172,5.85C4.172,6.25 4.225,6.626 4.331,6.979C4.438,7.329 4.611,7.614 4.852,7.833C5.092,8.048 5.416,8.156 5.822,8.156Z"
|
||||
android:fillColor="@color/text_white"/>
|
||||
</vector>
|
9
core-ui/src/main/res/drawable/ic_widget_chat.xml
Normal file
9
core-ui/src/main/res/drawable/ic_widget_chat.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M6.961,20C5.532,20 6.175,19.491 6.485,19.087C6.786,18.683 6.762,18.637 7.206,17.894C7.27,17.773 7.23,17.651 7.111,17.587C4.563,16.197 3,13.928 3,11.343C3,7.28 7,4 12,4C17,4 21,7.28 21,11.343C21,15.365 17.206,18.677 11.484,18.677C11.381,18.677 11.278,18.669 11.175,18.661C11.064,18.661 10.952,18.701 10.818,18.798C9.468,19.579 7.913,20 6.961,20Z"
|
||||
android:fillColor="@color/glyph_button"/>
|
||||
</vector>
|
|
@ -13,6 +13,8 @@ import kotlinx.coroutines.flow.Flow
|
|||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.scan
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
@ -26,6 +28,7 @@ interface ChatPreviewContainer {
|
|||
|
||||
suspend fun getAll(): List<Chat.Preview>
|
||||
suspend fun getPreview(space: SpaceId): Chat.Preview?
|
||||
fun observePreview(space: SpaceId) : Flow<Chat.Preview?>
|
||||
fun observePreviews() : Flow<List<Chat.Preview>>
|
||||
|
||||
class Default @Inject constructor(
|
||||
|
@ -113,6 +116,12 @@ interface ChatPreviewContainer {
|
|||
return previews.value.firstOrNull { preview -> preview.space.id == space.id }
|
||||
}
|
||||
|
||||
override fun observePreview(space: SpaceId): Flow<Chat.Preview?> {
|
||||
return previews.map {
|
||||
it.firstOrNull { preview -> preview.space.id == space.id }
|
||||
}
|
||||
}
|
||||
|
||||
override fun observePreviews(): Flow<List<Chat.Preview>> {
|
||||
return previews
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.anytypeio.anytype.domain.subscriptions
|
||||
|
||||
import com.anytypeio.anytype.domain.chats.ChatPreviewContainer
|
||||
import com.anytypeio.anytype.domain.device.DeviceTokenStoringService
|
||||
import com.anytypeio.anytype.domain.device.NetworkConnectionStatus
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
|
@ -21,7 +22,8 @@ interface GlobalSubscriptionManager {
|
|||
private val isSpaceDeleted: SpaceDeletedStatusWatcher,
|
||||
private val profile: ProfileSubscriptionManager,
|
||||
private val networkConnectionStatus: NetworkConnectionStatus,
|
||||
private val deviceTokenStoringService: DeviceTokenStoringService
|
||||
private val deviceTokenStoringService: DeviceTokenStoringService,
|
||||
private val chatPreviewContainer: ChatPreviewContainer
|
||||
) : GlobalSubscriptionManager {
|
||||
|
||||
override fun onStart() {
|
||||
|
@ -32,6 +34,7 @@ interface GlobalSubscriptionManager {
|
|||
profile.onStart()
|
||||
networkConnectionStatus.start()
|
||||
deviceTokenStoringService.start()
|
||||
chatPreviewContainer.start()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
|
@ -42,6 +45,7 @@ interface GlobalSubscriptionManager {
|
|||
profile.onStop()
|
||||
networkConnectionStatus.stop()
|
||||
deviceTokenStoringService.stop()
|
||||
chatPreviewContainer.stop()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ class ChatContainerTest {
|
|||
listOf(
|
||||
Event.Command.Chats.Delete(
|
||||
context = givenChatID,
|
||||
id = initialMsg.id,
|
||||
message = initialMsg.id,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -71,7 +71,9 @@ fun ChatTopToolbar(
|
|||
.noRippleClickable { onSpaceNameClicked() }
|
||||
,
|
||||
text = when(header) {
|
||||
is ChatViewModel.HeaderView.Default -> header.title
|
||||
is ChatViewModel.HeaderView.Default -> header.title.ifEmpty {
|
||||
stringResource(R.string.untitled)
|
||||
}
|
||||
is ChatViewModel.HeaderView.Init -> ""
|
||||
},
|
||||
color = colorResource(R.color.text_primary),
|
||||
|
|
|
@ -47,6 +47,7 @@ import com.anytypeio.anytype.domain.base.onSuccess
|
|||
import com.anytypeio.anytype.domain.bin.EmptyBin
|
||||
import com.anytypeio.anytype.domain.block.interactor.CreateBlock
|
||||
import com.anytypeio.anytype.domain.block.interactor.Move
|
||||
import com.anytypeio.anytype.domain.chats.ChatPreviewContainer
|
||||
import com.anytypeio.anytype.domain.collections.AddObjectToCollection
|
||||
import com.anytypeio.anytype.domain.dashboard.interactor.SetObjectListIsFavorite
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.CreateDataViewObject
|
||||
|
@ -122,6 +123,7 @@ import com.anytypeio.anytype.presentation.widgets.DropDownMenuAction
|
|||
import com.anytypeio.anytype.presentation.widgets.LinkWidgetContainer
|
||||
import com.anytypeio.anytype.presentation.widgets.ListWidgetContainer
|
||||
import com.anytypeio.anytype.presentation.widgets.SpaceBinWidgetContainer
|
||||
import com.anytypeio.anytype.presentation.widgets.SpaceChatWidgetContainer
|
||||
import com.anytypeio.anytype.presentation.widgets.SpaceWidgetContainer
|
||||
import com.anytypeio.anytype.presentation.widgets.TreePath
|
||||
import com.anytypeio.anytype.presentation.widgets.TreeWidgetBranchStateHolder
|
||||
|
@ -233,7 +235,8 @@ class HomeScreenViewModel(
|
|||
private val getSpaceInviteLink: GetSpaceInviteLink,
|
||||
private val deleteSpace: DeleteSpace,
|
||||
private val spaceMembers: ActiveSpaceMemberSubscriptionContainer,
|
||||
private val setAsFavourite: SetObjectListIsFavorite
|
||||
private val setAsFavourite: SetObjectListIsFavorite,
|
||||
private val chatPreviews: ChatPreviewContainer
|
||||
) : NavigationViewModel<HomeScreenViewModel.Navigation>(),
|
||||
Reducer<ObjectView, Payload>,
|
||||
WidgetActiveViewStateHolder by widgetActiveViewStateHolder,
|
||||
|
@ -507,6 +510,10 @@ class HomeScreenViewModel(
|
|||
|
||||
widgets.forceChatPosition().filter { widget -> widget.hasValidLayout() }.map { widget ->
|
||||
when (widget) {
|
||||
is Widget.Chat -> SpaceChatWidgetContainer(
|
||||
widget = widget,
|
||||
container = chatPreviews
|
||||
)
|
||||
is Widget.Link -> LinkWidgetContainer(
|
||||
widget = widget,
|
||||
fieldParser = fieldParser
|
||||
|
@ -1192,7 +1199,7 @@ class HomeScreenViewModel(
|
|||
)
|
||||
)
|
||||
}
|
||||
WidgetView.SpaceChat.id -> {
|
||||
BundledWidgetSourceIds.CHAT -> {
|
||||
proceedWithSpaceChatWidgetHeaderClick()
|
||||
}
|
||||
else -> {
|
||||
|
@ -1315,6 +1322,7 @@ class HomeScreenViewModel(
|
|||
}
|
||||
// All-objects widget has link appearance.
|
||||
is Widget.AllObjects -> Command.ChangeWidgetType.TYPE_LINK
|
||||
is Widget.Chat -> Command.ChangeWidgetType.TYPE_LINK
|
||||
}
|
||||
|
||||
// TODO move to a separate reducer inject into this VM's constructor
|
||||
|
@ -2690,7 +2698,8 @@ class HomeScreenViewModel(
|
|||
private val getSpaceInviteLink: GetSpaceInviteLink,
|
||||
private val deleteSpace: DeleteSpace,
|
||||
private val activeSpaceMemberSubscriptionContainer: ActiveSpaceMemberSubscriptionContainer,
|
||||
private val setObjectListIsFavorite: SetObjectListIsFavorite
|
||||
private val setObjectListIsFavorite: SetObjectListIsFavorite,
|
||||
private val chatPreviews: ChatPreviewContainer
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T = HomeScreenViewModel(
|
||||
|
@ -2748,7 +2757,8 @@ class HomeScreenViewModel(
|
|||
getSpaceInviteLink = getSpaceInviteLink,
|
||||
deleteSpace = this@Factory.deleteSpace,
|
||||
spaceMembers = activeSpaceMemberSubscriptionContainer,
|
||||
setAsFavourite = setObjectListIsFavorite
|
||||
setAsFavourite = setObjectListIsFavorite,
|
||||
chatPreviews = chatPreviews
|
||||
) as T
|
||||
}
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ class DataViewListWidgetContainer(
|
|||
)
|
||||
)
|
||||
}
|
||||
is Widget.Link, is Widget.Tree, is Widget.AllObjects -> {
|
||||
is Widget.Link, is Widget.Tree, is Widget.AllObjects, is Widget.Chat -> {
|
||||
throw IllegalStateException("Incompatible widget type.")
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ class DataViewListWidgetContainer(
|
|||
)
|
||||
)
|
||||
}
|
||||
is Widget.Tree, is Widget.Link, is Widget.AllObjects -> {
|
||||
is Widget.Tree, is Widget.Link, is Widget.AllObjects, is Widget.Chat -> {
|
||||
throw IllegalStateException("Incompatible widget type.")
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ class DataViewListWidgetContainer(
|
|||
limit = when (widget) {
|
||||
is Widget.List -> widget.limit
|
||||
is Widget.View -> widget.limit
|
||||
is Widget.Tree, is Widget.Link, is Widget.AllObjects -> {
|
||||
is Widget.Tree, is Widget.Link, is Widget.AllObjects, is Widget.Chat -> {
|
||||
throw IllegalStateException("Incompatible widget type.")
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ class DataViewListWidgetContainer(
|
|||
prettyPrintName = fieldParser.getObjectPluralName(widget.source.obj)
|
||||
)
|
||||
)
|
||||
is Widget.Link, is Widget.Tree, is Widget.AllObjects -> {
|
||||
is Widget.Link, is Widget.Tree, is Widget.AllObjects, is Widget.Chat -> {
|
||||
throw IllegalStateException("Incompatible widget type.")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,42 @@
|
|||
package com.anytypeio.anytype.presentation.widgets
|
||||
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.domain.chats.ChatPreviewContainer
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class SpaceChatWidgetContainer : WidgetContainer {
|
||||
override val view: Flow<WidgetView> = flowOf(
|
||||
WidgetView.SpaceChat
|
||||
)
|
||||
class SpaceChatWidgetContainer @Inject constructor(
|
||||
private val widget: Widget,
|
||||
private val container: ChatPreviewContainer
|
||||
) : WidgetContainer {
|
||||
override val view: Flow<WidgetView> = flow {
|
||||
emitAll(
|
||||
container
|
||||
.observePreview(space = SpaceId(widget.config.space))
|
||||
.map { preview ->
|
||||
(preview?.state?.unreadMessages?.counter ?: 0) to (preview?.state?.unreadMentions?.counter ?: 0)
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.map { (unreadMessageCount, unreadMentionCount) ->
|
||||
WidgetView.SpaceChat(
|
||||
id = widget.id,
|
||||
source = widget.source,
|
||||
unreadMessageCount = unreadMessageCount,
|
||||
unreadMentionCount = unreadMentionCount
|
||||
)
|
||||
}
|
||||
)
|
||||
}.catch {
|
||||
emit(
|
||||
WidgetView.SpaceChat(
|
||||
id = widget.id,
|
||||
source = widget.source
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -72,6 +72,13 @@ sealed class Widget {
|
|||
override val isAutoCreated: Boolean = false,
|
||||
) : Widget()
|
||||
|
||||
data class Chat(
|
||||
override val id: Id,
|
||||
override val source: Source.Bundled.Chat,
|
||||
override val config: Config,
|
||||
override val isAutoCreated: Boolean = false,
|
||||
) : Widget()
|
||||
|
||||
sealed class Source {
|
||||
|
||||
abstract val id: Id
|
||||
|
@ -172,69 +179,32 @@ fun List<Block>.parseWidgets(
|
|||
is Widget.Source.Default -> source.obj.isValid && source.obj.notDeletedNorArchived
|
||||
}
|
||||
if (hasValidSource && !WidgetConfig.excludedTypes.contains(source.type)) {
|
||||
if (source is Widget.Source.Bundled.AllObjects) {
|
||||
add(
|
||||
Widget.AllObjects(
|
||||
id = w.id,
|
||||
source = source,
|
||||
config = config,
|
||||
isAutoCreated = widgetContent.isAutoAdded
|
||||
when (source) {
|
||||
is Widget.Source.Bundled.AllObjects -> {
|
||||
add(
|
||||
Widget.AllObjects(
|
||||
id = w.id,
|
||||
source = source,
|
||||
config = config,
|
||||
isAutoCreated = widgetContent.isAutoAdded
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
when (widgetContent.layout) {
|
||||
Block.Content.Widget.Layout.TREE -> {
|
||||
add(
|
||||
Widget.Tree(
|
||||
id = w.id,
|
||||
source = source,
|
||||
limit = widgetContent.limit,
|
||||
config = config,
|
||||
isAutoCreated = widgetContent.isAutoAdded
|
||||
)
|
||||
}
|
||||
is Widget.Source.Bundled.Chat -> {
|
||||
add(
|
||||
Widget.Chat(
|
||||
id = w.id,
|
||||
source = source,
|
||||
config = config,
|
||||
isAutoCreated = widgetContent.isAutoAdded
|
||||
)
|
||||
}
|
||||
|
||||
Block.Content.Widget.Layout.LINK -> {
|
||||
add(
|
||||
Widget.Link(
|
||||
id = w.id,
|
||||
source = source,
|
||||
config = config,
|
||||
isAutoCreated = widgetContent.isAutoAdded
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Block.Content.Widget.Layout.LIST -> {
|
||||
add(
|
||||
Widget.List(
|
||||
id = w.id,
|
||||
source = source,
|
||||
limit = widgetContent.limit,
|
||||
config = config,
|
||||
isAutoCreated = widgetContent.isAutoAdded
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Block.Content.Widget.Layout.COMPACT_LIST -> {
|
||||
add(
|
||||
Widget.List(
|
||||
id = w.id,
|
||||
source = source,
|
||||
isCompact = true,
|
||||
limit = widgetContent.limit,
|
||||
config = config,
|
||||
isAutoCreated = widgetContent.isAutoAdded
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Block.Content.Widget.Layout.VIEW -> {
|
||||
if (source is Widget.Source.Default) {
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
when (widgetContent.layout) {
|
||||
Block.Content.Widget.Layout.TREE -> {
|
||||
add(
|
||||
Widget.View(
|
||||
Widget.Tree(
|
||||
id = w.id,
|
||||
source = source,
|
||||
limit = widgetContent.limit,
|
||||
|
@ -243,6 +213,56 @@ fun List<Block>.parseWidgets(
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
Block.Content.Widget.Layout.LINK -> {
|
||||
add(
|
||||
Widget.Link(
|
||||
id = w.id,
|
||||
source = source,
|
||||
config = config,
|
||||
isAutoCreated = widgetContent.isAutoAdded
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Block.Content.Widget.Layout.LIST -> {
|
||||
add(
|
||||
Widget.List(
|
||||
id = w.id,
|
||||
source = source,
|
||||
limit = widgetContent.limit,
|
||||
config = config,
|
||||
isAutoCreated = widgetContent.isAutoAdded
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Block.Content.Widget.Layout.COMPACT_LIST -> {
|
||||
add(
|
||||
Widget.List(
|
||||
id = w.id,
|
||||
source = source,
|
||||
isCompact = true,
|
||||
limit = widgetContent.limit,
|
||||
config = config,
|
||||
isAutoCreated = widgetContent.isAutoAdded
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Block.Content.Widget.Layout.VIEW -> {
|
||||
if (source is Widget.Source.Default) {
|
||||
add(
|
||||
Widget.View(
|
||||
id = w.id,
|
||||
source = source,
|
||||
limit = widgetContent.limit,
|
||||
config = config,
|
||||
isAutoCreated = widgetContent.isAutoAdded
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,10 +174,13 @@ sealed class WidgetView {
|
|||
override val isLoading: Boolean = false
|
||||
}
|
||||
|
||||
data object SpaceChat : WidgetView() {
|
||||
private const val SPACE_CHAT_WIDGET_ID = "bundled-widget.space-chat"
|
||||
data class SpaceChat(
|
||||
override val id: Id,
|
||||
val source: Widget.Source,
|
||||
val unreadMessageCount: Int = 0,
|
||||
val unreadMentionCount: Int = 0
|
||||
) : WidgetView() {
|
||||
override val isLoading: Boolean = false
|
||||
override val id: Id = SPACE_CHAT_WIDGET_ID
|
||||
}
|
||||
|
||||
sealed class SpaceWidget: WidgetView() {
|
||||
|
@ -200,7 +203,7 @@ sealed class WidgetView {
|
|||
}
|
||||
}
|
||||
|
||||
object EmptyState : WidgetView() {
|
||||
data object EmptyState : WidgetView() {
|
||||
override val id: Id get() = "id.widgets.empty.state"
|
||||
override val isLoading: Boolean = false
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue