-
Notifications
You must be signed in to change notification settings - Fork 384
feat(ui): channel page and floating UI #2748
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
renefloor
wants to merge
75
commits into
master
Choose a base branch
from
feat/channel-page
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
75 commits
Select commit
Hold shift + click to select a range
c9e00d4
Create ChannelPage with floating logic
renefloor 9e5ba93
simplify composer setup
renefloor e6e3444
poc for floating app bar
renefloor c99bc63
fixes for merge issues
renefloor 905b868
Revert "simplify composer setup"
renefloor bb28a92
fix avatar press
renefloor c6b4840
fix composer safeArea
renefloor 413e987
Add floating header
renefloor 66af712
Cleanup sample app
renefloor 2c156b2
Fix topPadding on listview
renefloor d42cc51
Fix attachment picker padding
renefloor 68f1ed0
Using theming for floating config
renefloor aac36c3
improve using default floatings from theme
renefloor 558f073
Use streamscaffold
renefloor 1ff997d
migrate to SDK navbar
renefloor 4bd8056
fix edit message in thread
renefloor 84e85ce
Add shadow to avatar on channel header
renefloor c27569b
Add gradient behind floating composer
renefloor 4b0a700
fix attachmentpicker background
renefloor cee1b1d
Add sample app config
renefloor 9ba1ba8
Fix extra padding on loading skeletons
renefloor dfedb96
Update all sample app pages
renefloor c431a3b
update core dependency
renefloor fb4f234
Add global message list config
renefloor 3ac8eb5
Fix scroll button showing on thread
renefloor cf907e7
Check if thread replies are enabled
renefloor 3e477cc
fix background attachment picker
renefloor 74888d1
set default appstyle to regular
renefloor a67a716
fix review comments
renefloor d1ad9e1
update core dependency
renefloor c44ba13
update changelog
renefloor 0c62f89
update core dependency
renefloor 738d676
fix(ui): channel page controller leak, shared fade helper, photo gall…
renefloor e966ad3
Update appstyle theming
renefloor faf7c8a
update core dependency
renefloor 01a5a71
Merge remote-tracking branch 'origin/master' into feat/channel-page
renefloor 38a0c59
update core dependency
renefloor 26d0f3f
chore: Update Goldens
renefloor 5730ff6
update core and fix analysis
renefloor 6b1db2a
add option for reply in channel config
renefloor 6593cc7
chore: Update Goldens
renefloor edd53f2
fix not using new api
renefloor 414fd1b
fix test and analysis
renefloor 017e9c4
Merge remote-tracking branch 'origin/master' into feat/channel-page
renefloor 3eb63d5
Merge remote-tracking branch 'origin/master' into feat/channel-page
renefloor 1862ec0
project update
renefloor 4490030
fix pixel artifact between components
renefloor 00ee06e
change background into 1 gradient
renefloor 2fc96e3
Add fixes for channelpage and deleted message
renefloor a9ad64c
Add snapshot tests for deleted message
renefloor f7ae533
chore: Update Goldens
renefloor a54b59e
Add floating to edit button group page
renefloor 0dd9add
use elevation for composer
renefloor d694d88
Add composer background animation
renefloor 775efe0
update core dependency
renefloor a0ea0e6
Merge remote-tracking branch 'origin/master' into feat/channel-page
renefloor 69df35a
update core dependency
renefloor d310daa
fix change in elevation logic
renefloor 989e58e
Merge remote-tracking branch 'origin/master' into feat/channel-page
renefloor 95cf893
fix(sample): restore location sharing in the channel page
renefloor e240ac2
docs(ui): document the channel/thread page extension points
renefloor 557b9ab
docs(changelog): correct the appBarBehavior entry
renefloor 14ed0a6
docs(changelog): note the thread scroll-to-bottom fix
renefloor ad9e6a6
fix(ui): resolve message list config on the build path
renefloor 33eeab5
test(ui): cover replies-disabled hiding the thread reply action
renefloor e97ab7f
refactor(ui): extract the app bar behavior resolver
renefloor 26ea9ff
chore: minor cleanups from PR review
renefloor d63dde3
Merge remote-tracking branch 'origin/master' into feat/channel-page
renefloor af5ec1e
move custom composer
renefloor 1a156e4
formatting
renefloor 42bfd56
minor improvements
renefloor e3e50b8
improvements on custom attachment picker
renefloor 4cf55e1
Merge branch 'fix/empty-unread-indicator' into feat/channel-page
renefloor bd3c0a2
fix test mocks
renefloor da535fb
Simplify back buttons in new pages
renefloor File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file modified
BIN
-349 Bytes
(99%)
docs/docs_screenshots/test/theming/goldens/macos/theming_red.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
200 changes: 200 additions & 0 deletions
200
packages/stream_chat_flutter/lib/src/channel/channel_page.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,200 @@ | ||
| import 'package:flutter/material.dart'; | ||
| import 'package:stream_chat_flutter/stream_chat_flutter.dart'; | ||
|
|
||
| /// A channel page with optional floating composer support. | ||
| /// | ||
| /// Wires up a [StreamChannelHeader], a [StreamMessageListView] and a | ||
| /// [StreamMessageComposer], laid out floating or docked according to the ambient | ||
| /// [StreamAppStyle]. Expects a [StreamChannel] ancestor. | ||
| /// | ||
| /// ## Customizing this page | ||
| /// | ||
| /// The constructor is deliberately small — most customization happens through | ||
| /// the component factory and the global configuration, both of which reach | ||
| /// inside this page because the components resolve them themselves. | ||
| /// | ||
| /// Swap out components with [streamChatComponentBuilders], passed to | ||
| /// [StreamChat.componentBuilders]: | ||
| /// | ||
| /// ```dart | ||
| /// StreamChat( | ||
| /// client: client, | ||
| /// componentBuilders: StreamComponentBuilders( | ||
| /// extensions: streamChatComponentBuilders( | ||
| /// // Applies to the messages this page's list renders. | ||
| /// messageItem: (context, props) => DefaultStreamMessageItem( | ||
| /// props: props.copyWith(maxWidth: 320), | ||
| /// ), | ||
| /// // Applies to this page's composer. | ||
| /// messageComposer: (context, props) => DefaultStreamMessageComposer( | ||
| /// props: props.copyWith(disableAttachments: true), | ||
| /// ), | ||
| /// ), | ||
| /// ), | ||
| /// child: child, | ||
| /// ) | ||
| /// ``` | ||
| /// | ||
| /// `messageItem`, `messageComposer`, `quotedMessage`, `mentionItem`, the | ||
| /// attachment builders, `mediaGallery` and `videoPlayer` all apply here. | ||
| /// | ||
| /// Change list behaviour — `swipeToReply`, `highlightInitialMessage`, | ||
| /// `autoScrollPolicy` and the rest — through | ||
| /// [StreamChatConfigurationData.messageListViewConfiguration] on | ||
| /// [StreamChat.configData]. | ||
| /// | ||
| /// Not reachable from here: the list-level slots on | ||
| /// [StreamMessageListViewBuilders] (`header`, `footer`, `dateDivider`, | ||
| /// `floatingDateDivider`, `threadSeparator`, `scrollToBottomButton`, `empty`, | ||
| /// `loading`, `error`) and [StreamChannelHeader]'s title, subtitle and actions. | ||
| /// Those have no component-factory entry, so customizing them means composing | ||
| /// [StreamMessageListView] and [StreamChannelHeader] directly instead of using | ||
| /// this page. | ||
| /// | ||
| /// See also: | ||
| /// | ||
| /// * [StreamThreadPage], the equivalent page for a single thread. | ||
| class StreamChannelPage extends StatefulWidget { | ||
| /// Creates a [StreamChannelPage]. | ||
| const StreamChannelPage({ | ||
| super.key, | ||
| this.initialScrollIndex, | ||
| this.initialAlignment, | ||
| this.onBackPressed, | ||
| this.onChannelAvatarPressed, | ||
| }); | ||
|
|
||
| /// Initial scroll index for the message list. | ||
| final int? initialScrollIndex; | ||
|
|
||
| /// Initial scroll alignment for the message list. | ||
| final double? initialAlignment; | ||
|
|
||
| /// Called when the header's back button is pressed. | ||
| /// | ||
| /// Replaces the default action, which pops the current route. When null the | ||
| /// default is kept. | ||
| final VoidCallback? onBackPressed; | ||
|
|
||
| /// Called when the default channel-avatar trailing is pressed. | ||
| final void Function(BuildContext context, Channel channel)? onChannelAvatarPressed; | ||
|
|
||
| @override | ||
| State<StreamChannelPage> createState() => _StreamChannelPageState(); | ||
| } | ||
|
|
||
| class _StreamChannelPageState extends State<StreamChannelPage> { | ||
| late final FocusNode _focusNode = FocusNode(); | ||
| late final StreamMessageComposerController _messageComposerController = StreamMessageComposerController(); | ||
|
|
||
| @override | ||
| void dispose() { | ||
| _focusNode.dispose(); | ||
| _messageComposerController.dispose(); | ||
| super.dispose(); | ||
| } | ||
|
|
||
| void _reply(Message message) { | ||
| _messageComposerController.quotedMessage = message; | ||
| WidgetsBinding.instance.addPostFrameCallback((_) { | ||
| if (!mounted) return; | ||
| _focusNode.requestFocus(); | ||
| }); | ||
| } | ||
|
|
||
| void _editMessage(Message message) { | ||
| _messageComposerController.editMessage(message); | ||
| WidgetsBinding.instance.addPostFrameCallback((_) { | ||
| if (!mounted) return; | ||
| _focusNode.requestFocus(); | ||
| }); | ||
| } | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| final appBar = StreamChannelHeader( | ||
| // Leaving this null keeps the header's default back button, which pops | ||
| // the route. | ||
| onBackPressed: widget.onBackPressed, | ||
| onChannelAvatarPressed: (channel) => widget.onChannelAvatarPressed?.call(context, channel), | ||
| ); | ||
|
|
||
| final composer = StreamMessageComposer( | ||
| focusNode: _focusNode, | ||
| messageComposerController: _messageComposerController, | ||
| onQuotedMessageCleared: _messageComposerController.clearQuotedMessage, | ||
| enableVoiceRecording: true, | ||
| ); | ||
|
|
||
| final typingIndicator = StreamTypingIndicator( | ||
| padding: const EdgeInsets.symmetric( | ||
| horizontal: 8, | ||
| vertical: 4, | ||
| ), | ||
| style: context.streamTextTheme.captionDefault.copyWith( | ||
| color: context.streamColorScheme.textSecondary, | ||
| ), | ||
| ); | ||
|
|
||
| return StreamScaffold( | ||
| appBar: appBar, | ||
| bottom: composer, | ||
| body: _ChannelPageBody( | ||
| initialScrollIndex: widget.initialScrollIndex, | ||
| initialAlignment: widget.initialAlignment, | ||
| onReply: _reply, | ||
| onEditMessage: _editMessage, | ||
| typingIndicator: typingIndicator, | ||
| ), | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| /// The body of [StreamChannelPage]. | ||
| /// | ||
| /// Reads [StreamScaffoldInsets] to provide correct [topPadding] and | ||
| /// [bottomPadding] to [StreamMessageListView], and positions the typing | ||
| /// indicator just above the composer (floating or docked) using the same | ||
| /// inset values. | ||
| class _ChannelPageBody extends StatelessWidget { | ||
| const _ChannelPageBody({ | ||
| required this.typingIndicator, | ||
| required this.onReply, | ||
| required this.onEditMessage, | ||
| this.initialScrollIndex, | ||
| this.initialAlignment, | ||
| }); | ||
|
|
||
| final Widget typingIndicator; | ||
| final void Function(Message) onReply; | ||
| final void Function(Message) onEditMessage; | ||
| final int? initialScrollIndex; | ||
| final double? initialAlignment; | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| final insets = StreamScaffoldInsets.of(context); | ||
|
|
||
| return Stack( | ||
| children: [ | ||
| StreamMessageListView( | ||
| initialScrollIndex: initialScrollIndex, | ||
| initialAlignment: initialAlignment, | ||
| onEditMessageTap: onEditMessage, | ||
| onReplyTap: onReply, | ||
| threadBuilder: (_, parentMessage) { | ||
| return StreamThreadPage(parent: parentMessage!); | ||
| }, | ||
| topPadding: insets.topPadding, | ||
| bottomPadding: insets.bottomPadding, | ||
| ), | ||
| Positioned( | ||
| bottom: insets.bottomPadding, | ||
| left: 0, | ||
| right: 0, | ||
| child: typingIndicator, | ||
| ), | ||
| ], | ||
| ); | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is from the HSL -> HCT color change