Skip to content

Commit 622b4ea

Browse files
authored
Droid 3622 add counters to space chat widget (#2449)
1 parent 5fe1d84 commit 622b4ea

File tree

15 files changed

+243
-97
lines changed

15 files changed

+243
-97
lines changed

app/src/main/java/com/anytypeio/anytype/di/feature/home/HomescreenDI.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
1111
import com.anytypeio.anytype.domain.bin.EmptyBin
1212
import com.anytypeio.anytype.domain.block.interactor.Move
1313
import com.anytypeio.anytype.domain.block.repo.BlockRepository
14+
import com.anytypeio.anytype.domain.chats.ChatPreviewContainer
1415
import com.anytypeio.anytype.domain.config.ConfigStorage
1516
import com.anytypeio.anytype.domain.config.UserSettingsRepository
1617
import com.anytypeio.anytype.domain.debugging.Logger
@@ -300,4 +301,5 @@ interface HomeScreenDependencies : ComponentDependencies {
300301
fun featureToggles(): FeatureToggles
301302
fun payloadDelegator(): PayloadDelegator
302303
fun fieldParser(): FieldParser
304+
fun chatPreviews(): ChatPreviewContainer
303305
}

app/src/main/java/com/anytypeio/anytype/di/main/SubscriptionsModule.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,15 +229,17 @@ object SubscriptionsModule {
229229
isSpaceDeleted: SpaceDeletedStatusWatcher,
230230
profileSubscriptionManager: ProfileSubscriptionManager,
231231
networkConnectionStatus: NetworkConnectionStatus,
232-
deviceTokenStoringService: DeviceTokenStoringService
232+
deviceTokenStoringService: DeviceTokenStoringService,
233+
chatPreviewContainer: ChatPreviewContainer
233234
): GlobalSubscriptionManager = GlobalSubscriptionManager.Default(
234235
types = types,
235236
relations = relations,
236237
permissions = permissions,
237238
isSpaceDeleted = isSpaceDeleted,
238239
profile = profileSubscriptionManager,
239240
networkConnectionStatus = networkConnectionStatus,
240-
deviceTokenStoringService = deviceTokenStoringService
241+
deviceTokenStoringService = deviceTokenStoringService,
242+
chatPreviewContainer = chatPreviewContainer
241243
)
242244

243245
@JvmStatic

app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreen.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,9 @@ private fun WidgetList(
499499
is WidgetView.SpaceChat -> {
500500
SpaceChatWidgetCard(
501501
mode = mode,
502-
onWidgetClicked = { onBundledWidgetHeaderClicked(item.id) }
502+
unReadMentionCount = item.unreadMentionCount,
503+
unReadMessageCount = item.unreadMessageCount,
504+
onWidgetClicked = { onWidgetSourceClicked(item.id, item.source) }
503505
)
504506
}
505507
is WidgetView.Action.EditWidgets -> {

app/src/main/java/com/anytypeio/anytype/ui/widgets/types/SpaceChatWidget.kt

Lines changed: 62 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@ import androidx.compose.foundation.Image
66
import androidx.compose.foundation.background
77
import androidx.compose.foundation.clickable
88
import androidx.compose.foundation.layout.Box
9+
import androidx.compose.foundation.layout.Row
10+
import androidx.compose.foundation.layout.Spacer
11+
import androidx.compose.foundation.layout.defaultMinSize
912
import androidx.compose.foundation.layout.fillMaxWidth
1013
import androidx.compose.foundation.layout.height
1114
import androidx.compose.foundation.layout.padding
15+
import androidx.compose.foundation.layout.size
16+
import androidx.compose.foundation.layout.width
17+
import androidx.compose.foundation.shape.CircleShape
1218
import androidx.compose.foundation.shape.RoundedCornerShape
1319
import androidx.compose.material.Text
1420
import androidx.compose.runtime.Composable
@@ -17,19 +23,24 @@ import androidx.compose.ui.Modifier
1723
import androidx.compose.ui.draw.clip
1824
import androidx.compose.ui.res.colorResource
1925
import androidx.compose.ui.res.painterResource
26+
import androidx.compose.ui.res.stringResource
2027
import androidx.compose.ui.text.style.TextOverflow
2128
import androidx.compose.ui.tooling.preview.Preview
2229
import androidx.compose.ui.unit.dp
2330
import com.anytypeio.anytype.R
31+
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
32+
import com.anytypeio.anytype.core_ui.views.Caption1Regular
2433
import com.anytypeio.anytype.core_ui.views.HeadlineSubheading
2534
import com.anytypeio.anytype.presentation.home.InteractionMode
2635

2736
@Composable
2837
fun SpaceChatWidgetCard(
2938
mode: InteractionMode,
30-
onWidgetClicked: () -> Unit = {}
39+
onWidgetClicked: () -> Unit = {},
40+
unReadMessageCount: Int = 0,
41+
unReadMentionCount: Int = 0
3142
) {
32-
Box(
43+
Row(
3344
modifier = Modifier
3445
.padding(start = 20.dp, end = 20.dp, top = 6.dp, bottom = 6.dp)
3546
.fillMaxWidth()
@@ -47,45 +58,76 @@ fun SpaceChatWidgetCard(
4758
} else {
4859
Modifier
4960
}
50-
)
61+
),
62+
verticalAlignment = Alignment.CenterVertically
5163
) {
5264
Image(
53-
painter = painterResource(id = R.drawable.ic_widget_all_content),
65+
painter = painterResource(id = R.drawable.ic_widget_chat),
5466
contentDescription = "All content icon",
5567
modifier = Modifier
56-
.align(Alignment.CenterStart)
5768
.padding(start = 16.dp)
5869
)
5970

6071
Text(
61-
// Temporary hard-coded name for the widget
62-
text = "Space chat",
72+
text = stringResource(R.string.chat),
6373
maxLines = 1,
6474
overflow = TextOverflow.Ellipsis,
6575
modifier = Modifier
66-
.align(Alignment.CenterStart)
67-
.padding(start = 44.dp, end = 16.dp),
76+
.weight(1f)
77+
.padding(start = 8.dp, end = 16.dp),
6878
style = HeadlineSubheading,
6979
color = colorResource(id = R.color.text_primary),
7080
)
7181

82+
if (unReadMentionCount > 0) {
83+
Box(
84+
modifier = Modifier
85+
.background(
86+
color = colorResource(R.color.transparent_active),
87+
shape = CircleShape
88+
)
89+
.size(20.dp),
90+
contentAlignment = Alignment.Center
91+
) {
92+
Image(
93+
painter = painterResource(R.drawable.ic_chat_widget_mention),
94+
contentDescription = null
95+
)
96+
}
97+
}
98+
99+
if (unReadMessageCount > 0) {
100+
if (unReadMentionCount > 0) {
101+
Spacer(modifier = Modifier.width(8.dp))
102+
}
103+
Box(
104+
modifier = Modifier
105+
.height(20.dp)
106+
.defaultMinSize(minWidth = 20.dp)
107+
.background(
108+
color = colorResource(R.color.transparent_active),
109+
shape = CircleShape
110+
),
111+
contentAlignment = Alignment.Center
112+
) {
113+
Text(
114+
text = unReadMentionCount.toString(),
115+
style = Caption1Regular,
116+
color = colorResource(id = R.color.text_white),
117+
)
118+
}
119+
Spacer(modifier = Modifier.width(16.dp))
120+
}
72121
}
73122
}
74123

75-
@Preview(
76-
name = "Dark Mode",
77-
showBackground = true,
78-
uiMode = UI_MODE_NIGHT_YES
79-
)
80-
@Preview(
81-
name = "Light Mode",
82-
showBackground = true,
83-
uiMode = UI_MODE_NIGHT_NO
84-
)
124+
@DefaultPreviews
85125
@Composable
86126
fun SpaceChatWidgetPreview() {
87127
SpaceChatWidgetCard(
88128
onWidgetClicked = {},
89-
mode = InteractionMode.Default
129+
mode = InteractionMode.Default,
130+
unReadMessageCount = 1,
131+
unReadMentionCount = 1
90132
)
91133
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="12dp"
3+
android:height="12dp"
4+
android:viewportWidth="12"
5+
android:viewportHeight="12">
6+
<path
7+
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"
8+
android:fillColor="@color/text_white"/>
9+
</vector>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24">
6+
<path
7+
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"
8+
android:fillColor="@color/glyph_button"/>
9+
</vector>

domain/src/main/java/com/anytypeio/anytype/domain/chats/ChatPreviewContainer.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import kotlinx.coroutines.flow.Flow
1313
import kotlinx.coroutines.flow.MutableStateFlow
1414
import kotlinx.coroutines.flow.catch
1515
import kotlinx.coroutines.flow.flowOn
16+
import kotlinx.coroutines.flow.map
17+
import kotlinx.coroutines.flow.mapNotNull
1618
import kotlinx.coroutines.flow.scan
1719
import kotlinx.coroutines.launch
1820

@@ -26,6 +28,7 @@ interface ChatPreviewContainer {
2628

2729
suspend fun getAll(): List<Chat.Preview>
2830
suspend fun getPreview(space: SpaceId): Chat.Preview?
31+
fun observePreview(space: SpaceId) : Flow<Chat.Preview?>
2932
fun observePreviews() : Flow<List<Chat.Preview>>
3033

3134
class Default @Inject constructor(
@@ -113,6 +116,12 @@ interface ChatPreviewContainer {
113116
return previews.value.firstOrNull { preview -> preview.space.id == space.id }
114117
}
115118

119+
override fun observePreview(space: SpaceId): Flow<Chat.Preview?> {
120+
return previews.map {
121+
it.firstOrNull { preview -> preview.space.id == space.id }
122+
}
123+
}
124+
116125
override fun observePreviews(): Flow<List<Chat.Preview>> {
117126
return previews
118127
}

domain/src/main/java/com/anytypeio/anytype/domain/subscriptions/GlobalSubscriptionManager.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.anytypeio.anytype.domain.subscriptions
22

3+
import com.anytypeio.anytype.domain.chats.ChatPreviewContainer
34
import com.anytypeio.anytype.domain.device.DeviceTokenStoringService
45
import com.anytypeio.anytype.domain.device.NetworkConnectionStatus
56
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
@@ -21,7 +22,8 @@ interface GlobalSubscriptionManager {
2122
private val isSpaceDeleted: SpaceDeletedStatusWatcher,
2223
private val profile: ProfileSubscriptionManager,
2324
private val networkConnectionStatus: NetworkConnectionStatus,
24-
private val deviceTokenStoringService: DeviceTokenStoringService
25+
private val deviceTokenStoringService: DeviceTokenStoringService,
26+
private val chatPreviewContainer: ChatPreviewContainer
2527
) : GlobalSubscriptionManager {
2628

2729
override fun onStart() {
@@ -32,6 +34,7 @@ interface GlobalSubscriptionManager {
3234
profile.onStart()
3335
networkConnectionStatus.start()
3436
deviceTokenStoringService.start()
37+
chatPreviewContainer.start()
3538
}
3639

3740
override fun onStop() {
@@ -42,6 +45,7 @@ interface GlobalSubscriptionManager {
4245
profile.onStop()
4346
networkConnectionStatus.stop()
4447
deviceTokenStoringService.stop()
48+
chatPreviewContainer.stop()
4549
}
4650
}
4751

domain/src/test/java/com/anytypeio/anytype/domain/chats/ChatContainerTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ class ChatContainerTest {
157157
listOf(
158158
Event.Command.Chats.Delete(
159159
context = givenChatID,
160-
id = initialMsg.id,
160+
message = initialMsg.id,
161161
)
162162
)
163163
)

feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/Toolbars.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ fun ChatTopToolbar(
7171
.noRippleClickable { onSpaceNameClicked() }
7272
,
7373
text = when(header) {
74-
is ChatViewModel.HeaderView.Default -> header.title
74+
is ChatViewModel.HeaderView.Default -> header.title.ifEmpty {
75+
stringResource(R.string.untitled)
76+
}
7577
is ChatViewModel.HeaderView.Init -> ""
7678
},
7779
color = colorResource(R.color.text_primary),

0 commit comments

Comments
 (0)