Last active
January 3, 2021 17:36
-
-
Save Nash0x7E2/70d7c4db70885099e5dded404a4d0a1d to your computer and use it in GitHub Desktop.
Resizing chat build with Flutter and @GetStream
This file contains 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
import 'package:flutter/material.dart'; | |
import 'package:stream_chat_flutter/stream_chat_flutter.dart'; | |
import './responsive_builder.dart'; | |
// This sample uses GetStream for chat. To get started, please see https://getstream.io/chat/flutter/tutorial/ | |
Future<void> main() async { | |
final Client streamClient = Client("YOUR-STREAM-KEY", persistenceEnabled: false); | |
await streamClient.setUser( | |
User( | |
id: 'YOUR-USER-ID', | |
extraData: { | |
'image': | |
'https://getstream.io/random_png/?id=still-grass-1&name=Still+grass', | |
}, | |
), | |
'YOUR-ACCESS-TOKEN', | |
); | |
runApp(StreamDesktop( | |
client: streamClient, | |
)); | |
} | |
class StreamDesktop extends StatelessWidget { | |
const StreamDesktop({Key key, this.client}) : super(key: key); | |
final Client client; | |
@override | |
Widget build(BuildContext context) { | |
return StreamChat( | |
client: client, | |
child: MaterialApp( | |
debugShowCheckedModeBanner: false, | |
home: ResponsiveBuilder( | |
smallChild: HomeSmallScreen(), | |
largeChild: HomeDesktopScreen(), | |
), | |
), | |
); | |
} | |
} | |
class HomeSmallScreen extends StatefulWidget { | |
@override | |
_HomeSmallScreenState createState() => _HomeSmallScreenState(); | |
} | |
class _HomeSmallScreenState extends State<HomeSmallScreen> { | |
PageController pageController; | |
int currentIndex = 0; | |
@override | |
void initState() { | |
super.initState(); | |
pageController = PageController(); | |
} | |
@override | |
void dispose() { | |
pageController.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
backgroundColor: Colors.white, | |
body: SafeArea( | |
child: PageView( | |
physics: NeverScrollableScrollPhysics(), | |
controller: pageController, | |
children: [ | |
ChannelListPage(), | |
Container( | |
decoration: BoxDecoration( | |
gradient: LinearGradient( | |
colors: [ | |
Color(0xFFc3fcff), | |
Color(0xFF6c74ff), | |
], | |
), | |
), | |
child: Center( | |
child: Card( | |
child: Padding( | |
padding: const EdgeInsets.symmetric( | |
horizontal: 48.0, vertical: 24.0), | |
child: Column( | |
mainAxisSize: MainAxisSize.min, | |
children: [ | |
ShaderMask( | |
shaderCallback: (rect) => LinearGradient(colors: [ | |
Color(0xFFc3fcff), | |
Color(0xFF6c74ff), | |
]).createShader(rect), | |
child: CircleAvatar( | |
radius: 48.0, | |
backgroundColor: Colors.white, | |
child: Text( | |
"N", | |
style: TextStyle(fontSize: 36.0), | |
), | |
), | |
), | |
const SizedBox(height: 12.0), | |
Text( | |
"Hello Nash 👋", | |
style: TextStyle( | |
fontSize: 16.0, fontWeight: FontWeight.w600), | |
), | |
const SizedBox(height: 36.0), | |
Text( | |
"ID: ${StreamChat.of(context).user.id}", | |
style: TextStyle( | |
fontSize: 12.0, | |
color: Colors.grey, | |
fontWeight: FontWeight.w600, | |
), | |
), | |
], | |
), | |
), | |
), | |
), | |
), | |
], | |
), | |
), | |
bottomNavigationBar: BottomNavigationBar( | |
currentIndex: currentIndex, | |
onTap: (int index) { | |
setState(() { | |
currentIndex = index; | |
}); | |
switch (index) { | |
case 0: | |
pageController.animateToPage(0, | |
duration: kThemeAnimationDuration, curve: Curves.ease); | |
break; | |
case 1: | |
pageController.animateToPage(1, | |
duration: kThemeAnimationDuration, curve: Curves.ease); | |
break; | |
default: | |
break; | |
} | |
}, | |
items: [ | |
BottomNavigationBarItem( | |
icon: Icon( | |
Icons.chat, | |
color: Color(0xFF3d91cc), | |
), | |
label: "Conversations", | |
), | |
BottomNavigationBarItem( | |
icon: Icon( | |
Icons.supervised_user_circle_rounded, | |
color: Color(0xFF6c74ff), | |
), | |
label: "Me", | |
), | |
], | |
), | |
); | |
} | |
} | |
class HomeDesktopScreen extends StatelessWidget { | |
final ValueNotifier<Channel> _selectedChannel = ValueNotifier(null); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
backgroundColor: Colors.white, | |
body: SafeArea( | |
child: Row( | |
children: [ | |
Expanded( | |
flex: 2, | |
child: Column( | |
children: [ | |
ListHeader(), | |
Divider(), | |
Expanded( | |
child: ChannelListPage( | |
onItemTap: (channel) => _selectedChannel.value = channel, | |
), | |
), | |
], | |
), | |
), | |
Expanded( | |
flex: 4, | |
child: ValueListenableBuilder( | |
valueListenable: _selectedChannel, | |
builder: (BuildContext context, value, placeholder) { | |
if (value == null) { | |
return placeholder; | |
} else { | |
return StreamChannel( | |
key: ValueKey<String>(value.cid), | |
channel: value, | |
child: ChannelPage( | |
showBackButton: false, | |
), | |
); | |
} | |
}, | |
child: GettingStarted(), | |
), | |
), | |
], | |
), | |
), | |
); | |
} | |
} | |
class ChannelPage extends StatelessWidget { | |
const ChannelPage({ | |
Key key, | |
this.showBackButton = true, | |
}) : super(key: key); | |
final bool showBackButton; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: ChannelHeader( | |
showBackButton: showBackButton, | |
), | |
body: Column( | |
children: <Widget>[ | |
Expanded( | |
child: MessageListView(), | |
), | |
MessageInput( | |
disableAttachments: true, | |
), | |
], | |
), | |
); | |
} | |
} | |
class ChannelListPage extends StatelessWidget { | |
const ChannelListPage({Key key, this.onItemTap}) : super(key: key); | |
final ValueChanged<Channel> onItemTap; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
backgroundColor: Colors.white, | |
body: ChannelsBloc( | |
child: ChannelListView( | |
onChannelTap: onItemTap != null | |
? (channel, _) { | |
onItemTap(channel); | |
} | |
: null, | |
filter: { | |
'members': { | |
'\$in': [StreamChat.of(context).user.id], | |
} | |
}, | |
sort: [SortOption('last_message_at')], | |
pagination: PaginationParams( | |
limit: 20, | |
), | |
channelWidget: ChannelPage(), | |
), | |
), | |
); | |
} | |
} | |
class GettingStarted extends StatelessWidget { | |
const GettingStarted({ | |
Key key, | |
}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return ShaderMask( | |
shaderCallback: (rect) => LinearGradient(colors: [ | |
Color(0xFFc3fcff), | |
Color(0xFF6c74ff), | |
]).createShader(rect), | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
crossAxisAlignment: CrossAxisAlignment.center, | |
children: [ | |
Icon( | |
Icons.chat, | |
size: 100.0, | |
color: Colors.white, | |
), | |
Text( | |
"Select a conversationt to get started!", | |
style: TextStyle( | |
color: Colors.white, | |
fontSize: 20.0, | |
fontWeight: FontWeight.w600, | |
), | |
), | |
], | |
), | |
); | |
} | |
} | |
class ListHeader extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Padding( | |
padding: const EdgeInsets.all(12.0), | |
child: Row( | |
children: [ | |
ShaderMask( | |
shaderCallback: (rect) => LinearGradient(colors: [ | |
Color(0xFFc3fcff), | |
Color(0xFF6c74ff), | |
]).createShader(rect), | |
child: CircleAvatar( | |
backgroundColor: Colors.white, | |
child: Text( | |
"N", | |
style: TextStyle(fontSize: 18.0), | |
), | |
), | |
), | |
const SizedBox(width: 12.0), | |
Text( | |
"Hello Nash 👋", | |
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w600), | |
), | |
], | |
), | |
); | |
} | |
} |
This file contains 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
import 'package:flutter/material.dart'; | |
class ResponsiveBuilder extends StatelessWidget { | |
const ResponsiveBuilder({ | |
Key key, | |
@required this.smallChild, | |
this.largeChild, | |
}) : super(key: key); | |
final Widget smallChild; | |
final Widget largeChild; | |
@override | |
Widget build(BuildContext context) { | |
return LayoutBuilder( | |
builder: (BuildContext context, BoxConstraints constraints) { | |
final isSmallDevice = constraints.maxWidth <= 800; | |
return AnimatedSwitcher( | |
duration: const Duration(milliseconds: 400), | |
child: (!isSmallDevice && largeChild != null) | |
? Builder( | |
key: ValueKey<String>("large-child-${largeChild.hashCode}"), | |
builder: (BuildContext context) => largeChild, | |
) | |
: Builder( | |
key: ValueKey<String>("small-child-${smallChild.hashCode}"), | |
builder: (BuildContext context) => smallChild, | |
), | |
); | |
}, | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment