@@ -20,9 +20,12 @@ import androidx.compose.foundation.layout.fillMaxWidth
2020import androidx.compose.foundation.layout.height
2121import androidx.compose.foundation.layout.padding
2222import androidx.compose.foundation.layout.size
23+ import androidx.compose.foundation.layout.statusBarsPadding
2324import androidx.compose.foundation.layout.width
2425import androidx.compose.material3.MaterialTheme
2526import androidx.compose.runtime.Composable
27+ import androidx.compose.runtime.LaunchedEffect
28+ import androidx.compose.runtime.SideEffect
2629import androidx.compose.ui.Modifier
2730import androidx.compose.ui.draw.drawWithContent
2831import androidx.compose.ui.geometry.Offset
@@ -37,9 +40,11 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
3740import androidx.compose.ui.unit.dp
3841import io.element.android.compound.theme.ElementTheme
3942import io.element.android.compound.tokens.generated.CompoundIcons
40- import io.element.android.features.knockrequests.impl.KnockRequest
4143import io.element.android.features.knockrequests.impl.R
42- import io.element.android.features.knockrequests.impl.getAvatarData
44+ import io.element.android.features.knockrequests.impl.data.KnockRequestPresentable
45+ import io.element.android.libraries.designsystem.components.async.AsyncIndicator
46+ import io.element.android.libraries.designsystem.components.async.AsyncIndicatorHost
47+ import io.element.android.libraries.designsystem.components.async.rememberAsyncIndicatorState
4348import io.element.android.libraries.designsystem.components.avatar.Avatar
4449import io.element.android.libraries.designsystem.components.avatar.AvatarSize
4550import io.element.android.libraries.designsystem.preview.ElementPreview
@@ -52,6 +57,7 @@ import io.element.android.libraries.designsystem.theme.components.Surface
5257import io.element.android.libraries.designsystem.theme.components.Text
5358import io.element.android.libraries.ui.strings.CommonStrings
5459import kotlinx.collections.immutable.ImmutableList
60+ import timber.log.Timber
5561
5662private const val MAX_AVATAR_COUNT = 3
5763
@@ -61,22 +67,42 @@ fun KnockRequestsBannerView(
6167 onViewRequestsClick : () -> Unit ,
6268 modifier : Modifier = Modifier ,
6369) {
64- AnimatedVisibility (
65- visible = state.isVisible,
66- enter = expandVertically(),
67- exit = shrinkVertically(),
68- modifier = modifier,
69- ) {
70- Surface (
71- shape = MaterialTheme .shapes.small,
72- color = ElementTheme .colors.bgCanvasDefaultLevel1,
73- shadowElevation = 24 .dp,
74- modifier = Modifier .padding(16 .dp),
70+ Box (modifier = modifier) {
71+ AnimatedVisibility (
72+ visible = state.isVisible,
73+ enter = expandVertically(),
74+ exit = shrinkVertically(),
7575 ) {
76- KnockRequestsBannerContent (
77- state = state,
78- onViewRequestsClick = onViewRequestsClick,
79- )
76+ Surface (
77+ shape = MaterialTheme .shapes.small,
78+ color = ElementTheme .colors.bgCanvasDefaultLevel1,
79+ shadowElevation = 24 .dp,
80+ modifier = Modifier .padding(16 .dp),
81+ ) {
82+ KnockRequestsBannerContent (
83+ state = state,
84+ onViewRequestsClick = onViewRequestsClick,
85+ )
86+ }
87+ }
88+ KnockRequestsAcceptErrorView (displayError = state.displayAcceptError)
89+ }
90+ }
91+
92+ @Composable
93+ private fun KnockRequestsAcceptErrorView (
94+ displayError : Boolean ,
95+ modifier : Modifier = Modifier ,
96+ ) {
97+ val asyncIndicatorState = rememberAsyncIndicatorState()
98+ AsyncIndicatorHost (modifier = modifier.statusBarsPadding(), state = asyncIndicatorState)
99+ LaunchedEffect (displayError) {
100+ if (displayError) {
101+ asyncIndicatorState.enqueue {
102+ AsyncIndicator .Custom (text = stringResource(CommonStrings .error_unknown))
103+ }
104+ } else {
105+ asyncIndicatorState.clear()
80106 }
81107 }
82108}
@@ -96,9 +122,9 @@ private fun KnockRequestsBannerContent(
96122 }
97123
98124 Column (
99- modifier
100- .fillMaxWidth()
101- .padding(all = 16 .dp)
125+ modifier
126+ .fillMaxWidth()
127+ .padding(all = 16 .dp)
102128 ) {
103129 Row {
104130 KnockRequestAvatarView (
@@ -122,13 +148,15 @@ private fun KnockRequestsBannerContent(
122148 )
123149 }
124150 }
151+ Spacer (modifier = Modifier .width(4 .dp))
125152 Icon (
126153 modifier = Modifier .clickable(onClick = ::onDismissClick),
127154 imageVector = CompoundIcons .Close (),
128155 contentDescription = stringResource(CommonStrings .action_close)
129156 )
130157 }
131- if (state.reason != null ) {
158+ val reason = state.reason
159+ if (! reason.isNullOrEmpty()) {
132160 Spacer (modifier = Modifier .height(16 .dp))
133161 Text (
134162 text = state.reason,
@@ -169,7 +197,7 @@ private fun KnockRequestsBannerContent(
169197
170198@Composable
171199private fun KnockRequestAvatarView (
172- knockRequests : ImmutableList <KnockRequest >,
200+ knockRequests : ImmutableList <KnockRequestPresentable >,
173201 modifier : Modifier = Modifier ,
174202) {
175203 Box (modifier) {
@@ -183,7 +211,7 @@ private fun KnockRequestAvatarView(
183211
184212@Composable
185213private fun KnockRequestAvatarListView (
186- knockRequests : ImmutableList <KnockRequest >,
214+ knockRequests : ImmutableList <KnockRequestPresentable >,
187215 modifier : Modifier = Modifier ,
188216) {
189217 val avatarSize = AvatarSize .KnockRequestBanner .dp
@@ -198,27 +226,27 @@ private fun KnockRequestAvatarListView(
198226 smallReversedList.forEachIndexed { index, knockRequest ->
199227 Avatar (
200228 modifier = Modifier
201- .padding(start = avatarSize / 2 * (lastItemIndex - index))
202- .graphicsLayer {
203- compositingStrategy = CompositingStrategy .Offscreen
204- }
205- .drawWithContent {
206- // Draw content and clear the pixels for the avatar on the left.
207- drawContent()
208- if (index < lastItemIndex) {
209- drawCircle(
210- color = Color .Black ,
211- center = Offset (
212- x = 0f ,
213- y = size.height / 2 ,
214- ),
215- radius = avatarSize.toPx() / 2 ,
216- blendMode = BlendMode .Clear ,
217- )
229+ .padding(start = avatarSize / 2 * (lastItemIndex - index))
230+ .graphicsLayer {
231+ compositingStrategy = CompositingStrategy .Offscreen
232+ }
233+ .drawWithContent {
234+ // Draw content and clear the pixels for the avatar on the left.
235+ drawContent()
236+ if (index < lastItemIndex) {
237+ drawCircle(
238+ color = Color .Black ,
239+ center = Offset (
240+ x = 0f ,
241+ y = size.height / 2 ,
242+ ),
243+ radius = avatarSize.toPx() / 2 ,
244+ blendMode = BlendMode .Clear ,
245+ )
246+ }
218247 }
219- }
220- .size(size = avatarSize)
221- .padding(2 .dp),
248+ .size(size = avatarSize)
249+ .padding(2 .dp),
222250 avatarData = knockRequest.getAvatarData(AvatarSize .KnockRequestBanner ),
223251 )
224252 }
0 commit comments