1
0
Fork 0
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:
Evgenii Kozlov 2025-05-23 19:01:21 +02:00 committed by GitHub
parent 5fe1d8489d
commit 622b4ea27c
Signed by: github
GPG key ID: B5690EEEBB952194
15 changed files with 249 additions and 103 deletions

View file

@ -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
}

View file

@ -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

View file

@ -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 -> {

View file

@ -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
)
}

View 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>

View 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>

View file

@ -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
}

View file

@ -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()
}
}

View file

@ -157,7 +157,7 @@ class ChatContainerTest {
listOf(
Event.Command.Chats.Delete(
context = givenChatID,
id = initialMsg.id,
message = initialMsg.id,
)
)
)

View file

@ -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),

View file

@ -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
}

View file

@ -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.")
}
}

View file

@ -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
)
)
}
}

View file

@ -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
)
)
}
}
}
}
}

View file

@ -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
}