Skip to content

Commit 1c0fe50

Browse files
committed
Bridge composer snackbar host via internal CompositionLocal.
Replace the public `MessageComposerParams.snackbarHostState` field (and the non-VM `MessageComposer` overload's parameter) with an internal `LocalMessageComposerSnackbarHostState`. The VM-bound composer provides the host so events can surface as snackbars; both the factory default and the non-VM overload read it from the local.
1 parent 67a83c7 commit 1c0fe50

4 files changed

Lines changed: 41 additions & 41 deletions

File tree

stream-chat-android-compose/api/stream-chat-android-compose.api

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1938,7 +1938,7 @@ public final class io/getstream/chat/android/compose/ui/messages/composer/Compos
19381938

19391939
public final class io/getstream/chat/android/compose/ui/messages/composer/MessageComposerKt {
19401940
public static final fun MessageComposer (Lio/getstream/chat/android/compose/viewmodel/messages/MessageComposerViewModel;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lio/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;III)V
1941-
public static final fun MessageComposer (Lio/getstream/chat/android/ui/common/state/messages/composer/MessageComposerState;Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/material3/SnackbarHostState;Lio/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;III)V
1941+
public static final fun MessageComposer (Lio/getstream/chat/android/ui/common/state/messages/composer/MessageComposerState;Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lio/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;III)V
19421942
}
19431943

19441944
public final class io/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions {
@@ -4708,8 +4708,8 @@ public final class io/getstream/chat/android/compose/ui/theme/MessageComposerLin
47084708

47094709
public final class io/getstream/chat/android/compose/ui/theme/MessageComposerParams {
47104710
public static final field $stable I
4711-
public fun <init> (Lio/getstream/chat/android/ui/common/state/messages/composer/MessageComposerState;Lkotlin/jvm/functions/Function4;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lio/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/material3/SnackbarHostState;)V
4712-
public synthetic fun <init> (Lio/getstream/chat/android/ui/common/state/messages/composer/MessageComposerState;Lkotlin/jvm/functions/Function4;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lio/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/material3/SnackbarHostState;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
4711+
public fun <init> (Lio/getstream/chat/android/ui/common/state/messages/composer/MessageComposerState;Lkotlin/jvm/functions/Function4;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lio/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)V
4712+
public synthetic fun <init> (Lio/getstream/chat/android/ui/common/state/messages/composer/MessageComposerState;Lkotlin/jvm/functions/Function4;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lio/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
47134713
public final fun component1 ()Lio/getstream/chat/android/ui/common/state/messages/composer/MessageComposerState;
47144714
public final fun component10 ()Lkotlin/jvm/functions/Function1;
47154715
public final fun component11 ()Lkotlin/jvm/functions/Function1;
@@ -4718,7 +4718,6 @@ public final class io/getstream/chat/android/compose/ui/theme/MessageComposerPar
47184718
public final fun component14 ()Lio/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions;
47194719
public final fun component15 ()Lkotlin/jvm/functions/Function1;
47204720
public final fun component16 ()Lkotlin/jvm/functions/Function0;
4721-
public final fun component17 ()Landroidx/compose/material3/SnackbarHostState;
47224721
public final fun component2 ()Lkotlin/jvm/functions/Function4;
47234722
public final fun component3 ()Landroidx/compose/ui/Modifier;
47244723
public final fun component4 ()Z
@@ -4727,8 +4726,8 @@ public final class io/getstream/chat/android/compose/ui/theme/MessageComposerPar
47274726
public final fun component7 ()Lkotlin/jvm/functions/Function1;
47284727
public final fun component8 ()Lkotlin/jvm/functions/Function1;
47294728
public final fun component9 ()Lkotlin/jvm/functions/Function0;
4730-
public final fun copy (Lio/getstream/chat/android/ui/common/state/messages/composer/MessageComposerState;Lkotlin/jvm/functions/Function4;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lio/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/material3/SnackbarHostState;)Lio/getstream/chat/android/compose/ui/theme/MessageComposerParams;
4731-
public static synthetic fun copy$default (Lio/getstream/chat/android/compose/ui/theme/MessageComposerParams;Lio/getstream/chat/android/ui/common/state/messages/composer/MessageComposerState;Lkotlin/jvm/functions/Function4;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lio/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Landroidx/compose/material3/SnackbarHostState;ILjava/lang/Object;)Lio/getstream/chat/android/compose/ui/theme/MessageComposerParams;
4729+
public final fun copy (Lio/getstream/chat/android/ui/common/state/messages/composer/MessageComposerState;Lkotlin/jvm/functions/Function4;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lio/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Lio/getstream/chat/android/compose/ui/theme/MessageComposerParams;
4730+
public static synthetic fun copy$default (Lio/getstream/chat/android/compose/ui/theme/MessageComposerParams;Lio/getstream/chat/android/ui/common/state/messages/composer/MessageComposerState;Lkotlin/jvm/functions/Function4;Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lio/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lio/getstream/chat/android/compose/ui/theme/MessageComposerParams;
47324731
public fun equals (Ljava/lang/Object;)Z
47334732
public final fun getInput ()Lkotlin/jvm/functions/Function4;
47344733
public final fun getMessageComposerState ()Lio/getstream/chat/android/ui/common/state/messages/composer/MessageComposerState;
@@ -4745,7 +4744,6 @@ public final class io/getstream/chat/android/compose/ui/theme/MessageComposerPar
47454744
public final fun getOnUserSelected ()Lkotlin/jvm/functions/Function1;
47464745
public final fun getOnValueChange ()Lkotlin/jvm/functions/Function1;
47474746
public final fun getRecordingActions ()Lio/getstream/chat/android/compose/ui/messages/composer/actions/AudioRecordingActions;
4748-
public final fun getSnackbarHostState ()Landroidx/compose/material3/SnackbarHostState;
47494747
public fun hashCode ()I
47504748
public final fun isAttachmentPickerVisible ()Z
47514749
public fun toString ()Ljava/lang/String;

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/composer/MessageComposer.kt

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import androidx.compose.runtime.LaunchedEffect
3434
import androidx.compose.runtime.collectAsState
3535
import androidx.compose.runtime.getValue
3636
import androidx.compose.runtime.remember
37+
import androidx.compose.runtime.staticCompositionLocalOf
3738
import androidx.compose.ui.Alignment
3839
import androidx.compose.ui.Alignment.Companion.Bottom
3940
import androidx.compose.ui.Modifier
@@ -170,32 +171,42 @@ public fun MessageComposer(
170171
}
171172
}
172173

173-
ChatTheme.componentFactory.MessageComposer(
174-
params = MessageComposerParams(
175-
modifier = modifier,
176-
isAttachmentPickerVisible = isAttachmentPickerVisible,
177-
onSendMessage = { text, attachments ->
178-
val messageWithData = viewModel.buildNewMessage(text, attachments)
179-
onSendMessage(messageWithData)
180-
},
181-
onUserSelected = onUserSelected,
182-
onCommandSelected = onCommandSelected,
183-
onAlsoSendToChannelSelected = onAlsoSendToChannelChange,
184-
onActiveCommandDismiss = onActiveCommandDismiss,
185-
snackbarHostState = snackbarHostState,
186-
recordingActions = recordingActions,
187-
input = input,
188-
messageComposerState = messageComposerState,
189-
onCancelAction = onCancelAction,
190-
onAttachmentsClick = onAttachmentsClick,
191-
onValueChange = onValueChange,
192-
onAttachmentRemoved = onAttachmentRemoved,
193-
onLinkPreviewClick = onLinkPreviewClick,
194-
onCancelLinkPreviewClick = onCancelLinkPreviewClick,
195-
),
196-
)
174+
CompositionLocalProvider(LocalMessageComposerSnackbarHostState provides snackbarHostState) {
175+
ChatTheme.componentFactory.MessageComposer(
176+
params = MessageComposerParams(
177+
modifier = modifier,
178+
isAttachmentPickerVisible = isAttachmentPickerVisible,
179+
onSendMessage = { text, attachments ->
180+
val messageWithData = viewModel.buildNewMessage(text, attachments)
181+
onSendMessage(messageWithData)
182+
},
183+
onUserSelected = onUserSelected,
184+
onCommandSelected = onCommandSelected,
185+
onAlsoSendToChannelSelected = onAlsoSendToChannelChange,
186+
onActiveCommandDismiss = onActiveCommandDismiss,
187+
recordingActions = recordingActions,
188+
input = input,
189+
messageComposerState = messageComposerState,
190+
onCancelAction = onCancelAction,
191+
onAttachmentsClick = onAttachmentsClick,
192+
onValueChange = onValueChange,
193+
onAttachmentRemoved = onAttachmentRemoved,
194+
onLinkPreviewClick = onLinkPreviewClick,
195+
onCancelLinkPreviewClick = onCancelLinkPreviewClick,
196+
),
197+
)
198+
}
197199
}
198200

201+
/**
202+
* Hands the [SnackbarHostState] from the VM-bound [MessageComposer] down to the factory's default
203+
* `MessageComposer` impl so that command-related events emitted by [MessageComposerViewModel] can
204+
* surface as snackbars rendered inside the composer's surface. Customer factory overrides may read
205+
* `current` to render the same snackbar; otherwise they will not see event-driven snackbars.
206+
*/
207+
internal val LocalMessageComposerSnackbarHostState =
208+
staticCompositionLocalOf<SnackbarHostState?> { null }
209+
199210
/**
200211
* Clean version of the [MessageComposer] that doesn't rely on ViewModels, so the user can provide a
201212
* manual way to handle and represent data and various operations.
@@ -215,9 +226,6 @@ public fun MessageComposer(
215226
* on disabled items.
216227
* @param onAlsoSendToChannelChange Handler when the "Also send to channel" checkbox is changed.
217228
* @param onActiveCommandDismiss Called when the user taps the dismiss button on the active command chip.
218-
* @param snackbarHostState Host used to display transient snackbars (validation errors and any
219-
* notices pushed by the caller). The VM-bound overload passes a host that it also drives from
220-
* [MessageComposerViewModel.events].
221229
* @param recordingActions The actions that can be performed on an audio recording.
222230
* @param input Customizable composable that represents the input field for the composer, [MessageInput] by default.
223231
*/
@@ -238,7 +246,6 @@ public fun MessageComposer(
238246
onCommandSelected: (Command) -> Unit = {},
239247
onAlsoSendToChannelChange: (Boolean) -> Unit = {},
240248
onActiveCommandDismiss: () -> Unit = {},
241-
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
242249
recordingActions: AudioRecordingActions = AudioRecordingActions.None,
243250
input: @Composable RowScope.(MessageComposerState) -> Unit = { state ->
244251
ChatTheme.componentFactory.MessageComposerInput(
@@ -261,6 +268,7 @@ public fun MessageComposer(
261268
val validationErrors = messageComposerState.validationErrors
262269
val userSuggestions = messageComposerState.mentionSuggestions
263270
val commandSuggestions = messageComposerState.commandSuggestions
271+
val snackbarHostState = LocalMessageComposerSnackbarHostState.current ?: remember { SnackbarHostState() }
264272

265273
MessageInputValidationError(
266274
validationErrors = validationErrors,

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactory.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import androidx.compose.material3.CenterAlignedTopAppBar
3737
import androidx.compose.material3.CircularProgressIndicator
3838
import androidx.compose.material3.ExperimentalMaterial3Api
3939
import androidx.compose.material3.Icon
40-
import androidx.compose.material3.SnackbarHostState
4140
import androidx.compose.material3.Text
4241
import androidx.compose.material3.TopAppBarDefaults
4342
import androidx.compose.material3.minimumInteractiveComponentSize
@@ -1208,7 +1207,6 @@ public interface ChatComponentFactory {
12081207
onCommandSelected = params.onCommandSelected,
12091208
onAlsoSendToChannelChange = params.onAlsoSendToChannelSelected,
12101209
onActiveCommandDismiss = params.onActiveCommandDismiss,
1211-
snackbarHostState = params.snackbarHostState ?: remember { SnackbarHostState() },
12121210
recordingActions = params.recordingActions,
12131211
input = params.input,
12141212
)

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatComponentFactoryParams.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import androidx.compose.foundation.lazy.LazyListState
2525
import androidx.compose.foundation.lazy.grid.LazyGridState
2626
import androidx.compose.material3.ExperimentalMaterial3Api
2727
import androidx.compose.material3.SnackbarData
28-
import androidx.compose.material3.SnackbarHostState
2928
import androidx.compose.material3.pulltorefresh.PullToRefreshState
3029
import androidx.compose.runtime.Composable
3130
import androidx.compose.ui.Alignment
@@ -907,8 +906,6 @@ public class SwipeToReplyContentParams
907906
* @param recordingActions The actions to control the audio recording.
908907
* @param onLinkPreviewClick Action invoked when a link preview is clicked.
909908
* @param onCancelLinkPreviewClick Action invoked when the cancel link preview button is clicked.
910-
* @param snackbarHostState Host used by the composer to render validation errors and any
911-
* notices pushed by the caller. `null` means the composer should create its own.
912909
*/
913910
public data class MessageComposerParams(
914911
val messageComposerState: MessageComposerState,
@@ -927,7 +924,6 @@ public data class MessageComposerParams(
927924
val recordingActions: AudioRecordingActions = AudioRecordingActions.None,
928925
val onLinkPreviewClick: ((LinkPreview) -> Unit)? = null,
929926
val onCancelLinkPreviewClick: (() -> Unit)? = null,
930-
val snackbarHostState: SnackbarHostState? = null,
931927
)
932928

933929
/**

0 commit comments

Comments
 (0)