Skip to content

Instantly share code, notes, and snippets.

@felideon
Created May 22, 2018 15:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save felideon/b99eaa4579390ffa50d45f35bc167169 to your computer and use it in GitHub Desktop.
Save felideon/b99eaa4579390ffa50d45f35bc167169 to your computer and use it in GitHub Desktop.
Friendlychat App
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