Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Swift
- Camera
- snackbar
- 문법
- reference
- Snapshot
- runTransaction
- transform
- changenotifierprovider
- changenotifier
- platformexception
- ListView.builder
- multiprovider
- divider
- setstate
- Navigator
- datetime
- Firebase
- borderRadius
- provider
- enum
- globalkey
- swift 문법
- controller
- signout
- user
- consumer
- Stream
- permission
- switch
Archives
- Today
- Total
코딩하는 제리
[Flutter/Project](Instagram Clone) 포스트 이미지 다운로드 링크 저장 본문
Flutter/Project_InstaClone(완)
[Flutter/Project](Instagram Clone) 포스트 이미지 다운로드 링크 저장
JerryCho 2021. 3. 2. 11:31소스코드 및 pubspec.yaml
// screens/share_post_screen.dart
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_project_IJ/constants/common_size.dart';
import 'package:flutter_project_IJ/constants/screen_size.dart';
import 'package:flutter_project_IJ/models/firestore/post_model.dart';
import 'package:flutter_project_IJ/models/firestore/user_model.dart';
import 'package:flutter_project_IJ/models/user_model_state.dart';
import 'package:flutter_project_IJ/repo/image_network_repository.dart';
import 'package:flutter_project_IJ/repo/post_network_repository.dart';
import 'package:flutter_project_IJ/widgets/my_progress_indicator.dart';
import 'package:flutter_tags/flutter_tags.dart';
import 'package:provider/provider.dart';
// TextEditingController를 위해 StatefulWidget로 변경
class SharePostScreen extends StatefulWidget {
final File imageFile;
final String postKey;
SharePostScreen(this.imageFile, {Key key, @required this.postKey})
: super(key: key);
@override
_SharePostScreenState createState() => _SharePostScreenState();
}
class _SharePostScreenState extends State<SharePostScreen> {
// 캡션 텍스트박스 컨트롤러
TextEditingController _textEditingController = TextEditingController();
List<String> _tagItems = [
"approval",
"pigeon",
"brown",
"expenditure",
"compromise",
"citizen",
"inspire",
"relieve",
"grave",
"incredible",
"voucher",
"girl",
"relax",
];
@override
void dispose() {
// 컨트롤러 종료
_textEditingController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('New Post'),
actions: [
TextButton(
onPressed: sharePostProcedure,
child: Text(
'Share',
textScaleFactor: 1.4,
style: TextStyle(color: Colors.blue),
),
)
],
),
body: ListView(
children: [
_captionWithImage(),
_divider,
_sectionButton('Tag People'),
_divider,
_sectionButton('Add Location'),
_tags(),
SizedBox(height: common_s_gap),
_divider,
SectionSwitch('Facebook'),
SectionSwitch('Instagram'),
SectionSwitch('Tumblr'),
_divider,
],
),
);
}
// 포스트 업로드/업데이트/다운로드
void sharePostProcedure() async {
showModalBottomSheet(
context: context,
builder: (_) => MyProgressIndicator(),
isDismissible: false /* 닫을 수 없음 */,
enableDrag: false /* 드래그 불가 */,
);
// 이미지 업로드
await imageNetworkRepository.uploadImage(widget.imageFile,
postKey: widget.postKey);
UserModel userModel =
Provider
.of<UserModelState>(context, listen: false)
.userModel;
// 포스트 생성
await postNetworkRepository.createNewPost(
widget.postKey,
PostModel.getMapForeCreatePost(
userKey: userModel.userKey,
username: userModel.username,
caption: _textEditingController.text));
// 이미지 다운로드 링크
String postImgLink = await imageNetworkRepository.getPostImageUrl(
widget.postKey);
// 위에서 포스트를 생성한 뒤에 postKey를 가져와서 업데이트
await postNetworkRepository.updatePostImageUrl(
postKey: widget.postKey, postImg: postImgLink);
// 팝업 창을 닫음
Navigator.of(context).pop();
// share_post_screen을 닫음
Navigator.of(context).pop();
}
Tags _tags() {
return Tags(
horizontalScroll: true,
itemCount: _tagItems.length,
heightHorizontalScroll: 30 /* 높이 */,
itemBuilder: (index) =>
ItemTags(
index: index,
title: _tagItems[index],
activeColor: Colors.grey[200],
textActiveColor: Colors.black87,
borderRadius: BorderRadius.circular(4) /* 테두리 둥글기 */,
elevation: 2 /* 그림자 */,
splashColor: Colors.grey[800] /* 선택효과 색상 */,
color: Colors.red /* 선택 색상 */,
),
);
}
Divider get _divider =>
Divider(
color: Colors.grey[300],
height: 1,
thickness: 1,
);
ListTile _sectionButton(String title) {
return ListTile(
title: Text(
title,
style: TextStyle(fontWeight: FontWeight.w400),
),
trailing: Icon(Icons.navigate_next),
dense: true,
/* 작게 만듦. */
contentPadding: EdgeInsets.symmetric(horizontal: common_gap),
);
}
ListTile _captionWithImage() {
return ListTile(
contentPadding: EdgeInsets.symmetric(
vertical: common_gap,
horizontal: common_gap,
),
leading: Image.file(
widget.imageFile,
width: size.width / 6,
height: size.width / 6,
fit: BoxFit.cover,
),
title: TextField(
controller: _textEditingController,
autofocus: true,
decoration: InputDecoration(
hintText: 'Wirte a caption...',
border: InputBorder.none,
),
),
);
}
}
// 버튼에 변화를 줘야함 = StatefulWidget
class SectionSwitch extends StatefulWidget {
final String _title;
const SectionSwitch(this._title, {
Key key,
}) : super(key: key);
@override
_SectionSwitchState createState() => _SectionSwitchState();
}
class _SectionSwitchState extends State<SectionSwitch> {
bool checked = false;
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(
widget._title,
style: TextStyle(fontWeight: FontWeight.w400),
),
trailing: CupertinoSwitch(
value: checked,
onChanged: (onValue) {
setState(() {
checked = onValue;
});
},
),
dense: true,
/* 작게 만듦. */
contentPadding: EdgeInsets.symmetric(horizontal: common_gap),
);
}
}
// repo/pst_network_repository.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_project_IJ/constants/firestore_keys.dart';
/*
포스트 데이터 업로드 과정
1. post reference를 가져옴(생성)
2. 어떤 포스트가 해당 유저에 포함되어 있는지 user reference를 가져옴
3. post collection과 user collection 두가지를 업데이트 해야하기에 transaction 사용.
4. user data에 postKey를 업데이트
5. post reference를 통해 post data를 업로드
*/
class PostNetworkRepository {
Future<void> createNewPost(
String postKey, Map<String, dynamic> postData) async {
// 1. post reference를 가져옴(생성)
final DocumentReference postRef =
FirebaseFirestore.instance.collection(COLLECTION_POSTS).doc(postKey);
// post reference를 통해 해당 document의 snapshot을 가져옴.
final DocumentSnapshot postSnapshot = await postRef.get();
// 2. 어떤 포스트가 해당 유저에 포함되어 있는지 user reference를 가져옴
final DocumentReference userRef = FirebaseFirestore.instance
.collection(COLLECTION_USERS)
.doc(postData[KEY_USERKEY]);
// 3. transaction -> 데이터 업로드에 하나라도 실패하면 이전의 데이터로 바꿔줌.
return FirebaseFirestore.instance.runTransaction((Transaction tx) async {
// 해당 postSnapshot이 존재하지 않으면
if (!postSnapshot.exists) {
// 4. 포스트 데이터 업로드
await tx.set(postRef, postData);
// 5. user의 mypost를 업데이트
// user reference에 postKey 추가
await tx.update(userRef, {
KEY_MYPOSTS: FieldValue.arrayUnion([postKey])
});
}
});
}
// postLink를 가져와서 저장
Future<void> updatePostImageUrl({String postImg, String postKey}) async {
// 1. post reference를 가져옴(생성)
final DocumentReference postRef =
FirebaseFirestore.instance.collection(COLLECTION_POSTS).doc(postKey);
// post reference를 통해 해당 document의 snapshot을 가져옴.
final DocumentSnapshot postSnapshot = await postRef.get();
// postSnapshot이 존재하면 업데이트
if (postSnapshot.exists) {
// KEY_POSTIMG에 받아온 postImg를 저장.
await postRef.update({KEY_POSTIMG: postImg});
}
}
}
PostNetworkRepository postNetworkRepository = PostNetworkRepository();
'Flutter > Project_InstaClone(완)' 카테고리의 다른 글
[Flutter/Project](Instagram Clone) search screen에 모든 유저 출력 (0) | 2021.03.02 |
---|---|
[Flutter/Project](Instagram Clone) 본인을 제외한 모든 유저 가져오기 (0) | 2021.03.02 |
[Flutter/Project](Instagram Clone) 포스트 데이터 업로드/업데이트 파일 작성 (0) | 2021.03.01 |
[Flutter/Project](Instagram Clone) 포스트 생성시 작성할 데이터 파일 post model (0) | 2021.02.27 |
[Flutter/Project](Instagram Clone) Firebase Storage Image Download (0) | 2021.02.25 |
Comments