開啟home_page.dart,把上傳照片的功能放在Drawer。
引入以下檔案:
import '../firebase/upload_storage.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';
import '../firebase/firestore_database.dart';
接著把原本的Side Drawer程式碼修改成以下:
class SideDrawer extends StatelessWidget {
final String email;
String imagePath;
SideDrawer({Key key, this.email}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: MediaQuery.of(context).size.width * 0.55,
child: Drawer(
child: ListView(
children: <Widget>[
UserAccountsDrawerHeader(
currentAccountPicture: FutureBuilder<String>(
future: getProfilePictureUrl(email),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.active:
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
break;
case ConnectionState.done:
if(snapshot.data != null)
return Image.network(snapshot.data);
return Container();
}
return null;
},
),
accountEmail: Text(email),
accountName: Text(''),
decoration: BoxDecoration(color: Colors.brown),
),
ListTile(
leading: Icon(Icons.file_upload),
title: Text('Profile picture'),
onTap: () async {
File image =
await ImagePicker.pickImage(source: ImageSource.gallery);
if (image != null) {
var uploadTask = uploadImage(image, email);
await uploadTask.onComplete;
String url =
await uploadTask.lastSnapshot.ref.getDownloadURL();
updateProfilePictureUrl(email, url);
}
},
),
ListTile(
leading: Icon(Icons.sentiment_satisfied),
title: Text('Rate Our App'),
onTap: () {
Navigator.of(context).pop();
_asyncScoreDialog(context);
},
),
ListTile(
leading: Icon(Icons.exit_to_app),
title: Text("Log out"),
onTap: () {
BlocProvider.of<AuthenticationBloc>(context)
.dispatch(LoggedOut());
},
),
ListTile(
leading: Icon(Icons.info),
title: Text("About"),
onTap: () {
SnackBar snackbar = SnackBar(
content:
Text('FlutTube是第十一屆iT邦幫忙鐵人賽的實作專案\n其中使用的電影資料由TMDb所提供'),
duration: Duration(seconds: 5),
);
Scaffold.of(context).showSnackBar(snackbar);
Navigator.of(context).pop();
},
)
],
),
),
);
}
}
由於getProfilePictureUrl()
回傳的是Future<String>
,所以currentAccountPicture這邊用FutureBuilder
取得處理的狀態,當資料處理完畢後就回傳Image Widget顯示圖片。
如果沒有回傳資料(snapshot.data is null),就放一個空白的container。
當使用者點擊Upload的選項後,先用ImagePicker
讓他從自己的圖片庫選取要上傳的照片。
選好照片後使用uploadImage
function上傳到Firebase Storage,接著等圖片上傳完成後取得下載連結,最後再存到Firestore裡。
File image = await ImagePicker.pickImage(source: ImageSource.gallery);
if (image != null) {
var uploadTask = uploadImage(image, email);
await uploadTask.onComplete;
String url = await uploadTask.lastSnapshot.ref.getDownloadURL();
updateProfilePictureUrl(email, url);
}
開啟home資料夾下的「comment_widget.dart」。
處理完上傳大頭貼的功能,接下來就是在每則使用者留言顯示他的大頭貼。
import 'package:flutter/material.dart';
import 'package:timeago/timeago.dart' as timeago;
import '../firebase/firestore_database.dart';
Widget commentWidget(String email, String content, var time) {
return Container(
padding: EdgeInsets.symmetric(vertical: 5),
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: Colors.black,
width: 3.0,
))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
height: 40,
width: 40,
child: FutureBuilder<String>(
future: getProfilePictureUrl(email),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.active:
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
break;
case ConnectionState.done:
if (snapshot.data.isEmpty)
return Image.asset(
'assets/no.jpg',
fit: BoxFit.fill,
);
return Image.network(
snapshot.data,
fit: BoxFit.fill,
);
}
return null;
},
),
),
SizedBox(
width: 5,
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(
email,
style: TextStyle(
fontSize: 16,
color: Colors.lightBlueAccent,
fontWeight: FontWeight.bold),
),
SizedBox(
width: 10,
),
Text(
timeago.format(time.toDate()),
style: TextStyle(
fontSize: 8,
color: Colors.grey,
),
),
],
),
SizedBox(
height: 5.0,
),
ConstrainedBox(
constraints: BoxConstraints(maxWidth: 300, maxHeight: 1000),
child: Container(
child: Text(
content,
style: TextStyle(
fontSize: 14,
),
),
),
),
],
),
],
));
}
這裡一樣使用FutureBuilder
去監聽Future處理的狀態,為了讓每個人的圖片大小都一樣,所以用Container包裹住並設定圖片採用BoxFit.fill
的方式填滿。
加上大頭貼後的留言果然像樣多了,我想FlutTube這個App的功能都做得差不多了,不過既然離完賽還有3天,明天就繼續來介紹Firebase中我很喜歡的一個功能「Cloud Messaging」,之後就可以隨時傳遞通知給App的使用者。
完整程式碼在這裡-> FlutTube Github