Created
May 22, 2018 15:31
-
-
Save felideon/b99eaa4579390ffa50d45f35bc167169 to your computer and use it in GitHub Desktop.
Friendlychat App
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
import 'dart:async'; | |
import 'dart:io'; | |
import 'dart:math'; | |
import 'package:firebase_analytics/firebase_analytics.dart'; | |
import 'package:firebase_auth/firebase_auth.dart'; | |
import 'package:firebase_database/firebase_database.dart'; | |
import 'package:firebase_database/ui/firebase_animated_list.dart'; | |
import 'package:firebase_storage/firebase_storage.dart'; | |
import 'package:flutter/cupertino.dart'; | |
import 'package:flutter/foundation.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:google_sign_in/google_sign_in.dart'; | |
import 'package:image_picker/image_picker.dart'; | |
final auth = FirebaseAuth.instance; | |
final analytics = new FirebaseAnalytics(); | |
final googleSignIn = new GoogleSignIn(); | |
final reference = FirebaseDatabase.instance.reference().child('messages'); | |
void main() => runApp(new FriendlychatApp()); | |
final ThemeData kIOSTheme = new ThemeData( | |
primarySwatch: Colors.orange, | |
primaryColor: Colors.grey[100], | |
primaryColorBrightness: Brightness.light, | |
); | |
final ThemeData kDefaultTheme = new ThemeData( | |
primarySwatch: Colors.purple, | |
accentColor: Colors.orangeAccent[400], | |
); | |
class FriendlychatApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return new MaterialApp( | |
title: "Friendlychat", | |
theme: defaultTargetPlatform == TargetPlatform.iOS | |
? kIOSTheme : kDefaultTheme, | |
home: new ChatScreen(), | |
); | |
} | |
} | |
class ChatMessage extends StatelessWidget { | |
ChatMessage({this.snapshot, this.animation}); | |
final DataSnapshot snapshot; | |
final Animation animation; | |
@override | |
Widget build(BuildContext context) { | |
return new FadeTransition( | |
opacity: new CurvedAnimation( | |
parent: animation, curve: Curves.easeOut | |
), | |
child: new Container( | |
margin: const EdgeInsets.symmetric(vertical: 10.0), | |
child: new Row( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: <Widget>[ | |
new Container( | |
margin: const EdgeInsets.only(right: 16.0), | |
child: new CircleAvatar( | |
backgroundImage: new NetworkImage(snapshot.value['senderPhotoUrl']), | |
), | |
), | |
new Expanded( | |
child: new Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: <Widget>[ | |
new Text( | |
snapshot.value['senderName'], | |
style: Theme.of(context).textTheme.subhead | |
), | |
new Container( | |
margin: const EdgeInsets.only(top: 5.0), | |
child: snapshot.value['imageUrl'] != null ? | |
new Image.network( | |
snapshot.value['imageUrl'], | |
width: 250.0, | |
) : new Text(snapshot.value['text']), | |
), | |
], | |
), | |
), | |
], | |
), | |
), | |
); | |
} | |
} | |
class ChatScreen extends StatefulWidget { | |
@override | |
State createState() => new ChatScreenState(); | |
} | |
class ChatScreenState extends State<ChatScreen> { | |
final TextEditingController _textController = new TextEditingController(); | |
bool _isComposing = false; | |
Future<Null> _ensureLoggedIn() async { | |
GoogleSignInAccount user = googleSignIn.currentUser; | |
if (user == null) { | |
user = await googleSignIn.signInSilently(); | |
} | |
if (user == null) { | |
await googleSignIn.signIn(); | |
analytics.logLogin(); | |
} | |
if (await auth.currentUser() == null) { | |
GoogleSignInAuthentication credentials = await googleSignIn.currentUser.authentication; | |
await auth.signInWithGoogle( | |
idToken: credentials.idToken, | |
accessToken: credentials.accessToken, | |
); | |
} | |
} | |
void _handleSubmitted(String text) async { | |
_textController.clear(); | |
setState(() { | |
_isComposing = false; | |
}); | |
await _ensureLoggedIn(); | |
_sendMessage(text: text); | |
} | |
void _sendMessage({ String text, String imageUrl }) { | |
reference.push().set({ | |
'text': text, | |
'imageUrl': imageUrl, | |
'senderName': googleSignIn.currentUser.displayName, | |
'senderPhotoUrl': googleSignIn.currentUser.photoUrl, | |
}); | |
// ChatMessage message = new ChatMessage( | |
// text: text, | |
// animationController: new AnimationController( | |
// duration: new Duration(milliseconds: 700), | |
// vsync: this, | |
// ), | |
// ); | |
// setState(() { _messages.insert(0, message); }); | |
// message.animationController.forward(); | |
analytics.logEvent(name: "send_message"); | |
} | |
Widget _buildTextComposer() { | |
return new IconTheme( | |
data: new IconThemeData(color: Theme.of(context).accentColor), | |
child: new Container( | |
margin: const EdgeInsets.symmetric(horizontal: 8.0), | |
child: new Row( | |
children: <Widget>[ | |
new Container( | |
margin: const EdgeInsets.symmetric(horizontal: 8.0), | |
child: new IconButton( | |
icon: new Icon(Icons.photo_camera), | |
onPressed: () async { | |
await _ensureLoggedIn(); | |
File imageFile = await ImagePicker.pickImage(source: ImageSource.gallery); | |
int random = new Random().nextInt(100000); | |
StorageReference ref = FirebaseStorage.instance.ref().child("image_$random.jpg"); | |
StorageUploadTask uploadTask = ref.putFile(imageFile); | |
Uri downloadUrl = (await uploadTask.future).downloadUrl; | |
_sendMessage(imageUrl: downloadUrl.toString()); | |
}, | |
), | |
), | |
new Flexible( | |
child: new TextField( | |
controller: _textController, | |
onChanged: (String text) { | |
setState(() { | |
_isComposing = text.length > 0; | |
}); | |
}, | |
onSubmitted: _handleSubmitted, | |
decoration: new InputDecoration.collapsed( | |
hintText: "Send a message", | |
), | |
), | |
), | |
new Container( | |
margin: new EdgeInsets.symmetric(horizontal: 4.0), | |
child: Theme.of(context).platform == TargetPlatform.iOS ? | |
new CupertinoButton( | |
child: new Text("Send"), | |
onPressed: _isComposing | |
? () => _handleSubmitted(_textController.text) : null, | |
) | |
: | |
new IconButton( | |
icon: new Icon(Icons.send), | |
onPressed: _isComposing | |
? () => _handleSubmitted(_textController.text) : null, | |
), | |
), | |
], | |
), | |
), | |
); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return new Scaffold( | |
appBar: new AppBar( | |
title: new Text("Friendlychat"), | |
elevation: Theme.of(context).platform == TargetPlatform.iOS ? 0.0 : 4.0, | |
), | |
body: new Column( | |
children: <Widget>[ | |
new Flexible( | |
child: new FirebaseAnimatedList( | |
query: reference, | |
sort: (a, b) => b.key.compareTo(a.key), | |
padding: new EdgeInsets.all(8.0), | |
reverse: true, | |
itemBuilder: (_, DataSnapshot snapshot, Animation<double> animation, int index) { | |
return new ChatMessage( | |
snapshot: snapshot, | |
animation: animation, | |
); | |
}, | |
), | |
), | |
new Divider(height: 1.0), | |
new Container( | |
decoration: new BoxDecoration(color: Theme.of(context).cardColor), | |
child: _buildTextComposer(), | |
), | |
], | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment