Skip to content

Commit 86a1106

Browse files
committed
🚧 Add bookmark to tweet
1 parent a82da9b commit 86a1106

File tree

8 files changed

+278
-11
lines changed

8 files changed

+278
-11
lines changed

ios/.gitignore

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
*.mode1v3
2+
*.mode2v3
3+
*.moved-aside
4+
*.pbxuser
5+
*.perspectivev3
6+
**/*sync/
7+
.sconsign.dblite
8+
.tags*
9+
**/.vagrant/
10+
**/DerivedData/
11+
Icon?
12+
**/Pods/
13+
**/.symlinks/
14+
profile
15+
xcuserdata
16+
**/.generated/
17+
Flutter/App.framework
18+
Flutter/Flutter.framework
19+
Flutter/Flutter.podspec
20+
Flutter/Generated.xcconfig
21+
Flutter/app.flx
22+
Flutter/app.zip
23+
Flutter/flutter_assets/
24+
Flutter/flutter_export_environment.sh
25+
ServiceDefinitions.json
26+
Runner/GeneratedPluginRegistrant.*
27+
28+
# Exceptions to above rules.
29+
!default.mode1v3
30+
!default.mode2v3
31+
!default.pbxuser
32+
!default.perspectivev3
33+
34+
/build

lib/model/bookmarkModel.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class BookmarkModel {
2+
String key;
3+
String tweetId;
4+
String createdAt;
5+
BookmarkModel({
6+
this.key,
7+
this.tweetId,
8+
this.createdAt,
9+
});
10+
11+
factory BookmarkModel.fromJson(Map<dynamic, dynamic> json) => BookmarkModel(
12+
key: json["tweetId"],
13+
tweetId: json["tweetId"],
14+
createdAt: json["created_at"],
15+
);
16+
17+
Map<String, dynamic> toJson() => {
18+
"key": key,
19+
"tweetId": tweetId,
20+
"created_at": createdAt,
21+
};
22+
}

lib/state/bookmarkState.dart

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import 'dart:async';
2+
3+
import 'package:firebase_database/firebase_database.dart';
4+
import 'package:flutter_twitter_clone/helper/shared_prefrence_helper.dart';
5+
import 'package:flutter_twitter_clone/helper/utility.dart';
6+
import 'package:flutter_twitter_clone/model/bookmarkModel.dart';
7+
import 'package:flutter_twitter_clone/model/feedModel.dart';
8+
import 'package:flutter_twitter_clone/ui/page/common/locator.dart';
9+
import 'appState.dart';
10+
11+
class BookmarkState extends AppState {
12+
BookmarkState() {
13+
getDataFromDatabase();
14+
}
15+
List<FeedModel> _tweetList;
16+
List<BookmarkModel> _bookmarkList;
17+
18+
addBookmarkTweetToList(BookmarkModel model) {
19+
if (_bookmarkList == null) {
20+
_bookmarkList = <BookmarkModel>[];
21+
}
22+
23+
if (!_bookmarkList.any((element) => element.key == model.key)) {
24+
_bookmarkList.add(model);
25+
}
26+
}
27+
28+
List<FeedModel> get tweetList => _tweetList;
29+
30+
/// get [Notification list] from firebase realtime database
31+
void getDataFromDatabase() async {
32+
String userId = await getIt<SharedPreferenceHelper>()
33+
.getUserProfile()
34+
.then((value) => value.userId);
35+
try {
36+
if (_tweetList != null) {
37+
return;
38+
}
39+
loading = true;
40+
kDatabase
41+
.child('bookmark')
42+
.child(userId)
43+
.once()
44+
.then((DataSnapshot snapshot) async {
45+
if (snapshot.value != null) {
46+
var map = snapshot.value as Map<dynamic, dynamic>;
47+
if (map != null) {
48+
map.forEach((bookmarkKey, value) {
49+
var map = value as Map<dynamic, dynamic>;
50+
var model = BookmarkModel.fromJson(map);
51+
model.key = bookmarkKey;
52+
addBookmarkTweetToList(model);
53+
});
54+
}
55+
56+
if (_bookmarkList != null) {
57+
for (var bookmark in _bookmarkList) {
58+
var tweet = await getTweetDetail(bookmark.tweetId);
59+
if (tweet != null) {
60+
if (_tweetList == null) {
61+
_tweetList = <FeedModel>[];
62+
}
63+
_tweetList.add(tweet);
64+
}
65+
}
66+
}
67+
}
68+
loading = false;
69+
});
70+
} catch (error) {
71+
loading = false;
72+
cprint(error, errorIn: 'getDataFromDatabase');
73+
}
74+
}
75+
76+
/// get `Tweet` present in notification
77+
Future<FeedModel> getTweetDetail(String tweetId) async {
78+
FeedModel _tweetDetail;
79+
var snapshot = await kDatabase.child('tweet').child(tweetId).once();
80+
if (snapshot.value != null) {
81+
var map = snapshot.value as Map<dynamic, dynamic>;
82+
_tweetDetail = FeedModel.fromJson(map);
83+
_tweetDetail.key = snapshot.key;
84+
return _tweetDetail;
85+
} else {
86+
return null;
87+
}
88+
}
89+
}

lib/state/feedState.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import 'package:firebase_database/firebase_database.dart';
44
import 'package:firebase_database/firebase_database.dart' as dabase;
55
import 'package:firebase_storage/firebase_storage.dart';
66
import 'package:flutter_twitter_clone/helper/enum.dart';
7+
import 'package:flutter_twitter_clone/helper/shared_prefrence_helper.dart';
78
import 'package:flutter_twitter_clone/model/feedModel.dart';
89
import 'package:flutter_twitter_clone/helper/utility.dart';
910
import 'package:flutter_twitter_clone/model/user.dart';
1011
import 'package:flutter_twitter_clone/state/appState.dart';
12+
import 'package:flutter_twitter_clone/ui/page/common/locator.dart';
1113
import 'package:path/path.dart' as Path;
1214
// import 'authState.dart';
1315

@@ -452,6 +454,15 @@ class FeedState extends AppState {
452454
notifyListeners();
453455
}
454456

457+
/// Add Tweet in bookmark
458+
Future addBookmark(String tweetId) async {
459+
final pref = getIt<SharedPreferenceHelper>();
460+
var userId = await pref.getUserProfile().then((value) => value.userId);
461+
DatabaseReference dbReference =
462+
kDatabase.child('bookmark').child(userId).child(tweetId);
463+
await dbReference.set({"tweetId": tweetId});
464+
}
465+
455466
/// Trigger when any tweet changes or update
456467
/// When any tweet changes it update it in UI
457468
/// No matter if Tweet is in home page or in detail page or in comment section.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_twitter_clone/helper/enum.dart';
3+
import 'package:flutter_twitter_clone/model/feedModel.dart';
4+
import 'package:flutter_twitter_clone/state/bookmarkState.dart';
5+
import 'package:flutter_twitter_clone/ui/theme/theme.dart';
6+
import 'package:flutter_twitter_clone/widgets/customAppBar.dart';
7+
import 'package:flutter_twitter_clone/widgets/newWidget/emptyList.dart';
8+
import 'package:flutter_twitter_clone/widgets/tweet/tweet.dart';
9+
import 'package:provider/provider.dart';
10+
11+
class BookmarkPage extends StatelessWidget {
12+
const BookmarkPage({Key key}) : super(key: key);
13+
14+
static Route<T> getRoute<T>() {
15+
return MaterialPageRoute(
16+
builder: (_) {
17+
return Provider(
18+
create: (_) => BookmarkState(),
19+
child: ChangeNotifierProvider(
20+
create: (BuildContext context) => BookmarkState(),
21+
builder: (_, child) => BookmarkPage(),
22+
),
23+
);
24+
},
25+
);
26+
}
27+
28+
@override
29+
Widget build(BuildContext context) {
30+
return Scaffold(
31+
backgroundColor: TwitterColor.mystic,
32+
appBar: CustomAppBar(
33+
title: Text("Bookmark", style: TextStyles.titleStyle),
34+
isBackButton: true,
35+
),
36+
body: BookmarkPageBody(),
37+
);
38+
}
39+
}
40+
41+
class BookmarkPageBody extends StatelessWidget {
42+
const BookmarkPageBody({Key key}) : super(key: key);
43+
44+
Widget _tweet(BuildContext context, FeedModel model) {
45+
return Container(
46+
color: Colors.white,
47+
child: Tweet(
48+
model: model,
49+
type: TweetType.Tweet,
50+
),
51+
);
52+
}
53+
54+
@override
55+
Widget build(BuildContext context) {
56+
var state = Provider.of<BookmarkState>(context);
57+
var list = state.tweetList;
58+
if (state.isbusy) {
59+
return SizedBox(
60+
height: 3,
61+
child: LinearProgressIndicator(),
62+
);
63+
} else if (list == null || list.isEmpty) {
64+
return Padding(
65+
padding: EdgeInsets.symmetric(horizontal: 30),
66+
child: EmptyList(
67+
'No Bookmark available yet',
68+
subTitle: 'When new bookmark found, they\'ll show up here.',
69+
),
70+
);
71+
}
72+
return ListView.builder(
73+
addAutomaticKeepAlives: true,
74+
itemBuilder: (context, index) => _tweet(context, list[index]),
75+
itemCount: list.length,
76+
);
77+
}
78+
}

lib/ui/page/common/sidebar.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_twitter_clone/helper/constant.dart';
33
import 'package:flutter_twitter_clone/state/authState.dart';
4+
import 'package:flutter_twitter_clone/ui/page/bookmark/bookmarkPage.dart';
45
import 'package:flutter_twitter_clone/ui/page/profile/follow/followerListPage.dart';
56
import 'package:flutter_twitter_clone/ui/page/profile/profilePage.dart';
67
import 'package:flutter_twitter_clone/ui/page/profile/qrCode/scanner.dart';
@@ -255,7 +256,14 @@ class _SidebarMenuState extends State<SidebarMenu> {
255256
context, ProfilePage.getRoute(profileId: state.userId));
256257
}),
257258
_menuListRowButton('Lists', icon: AppIcon.lists),
258-
_menuListRowButton('Bookmark', icon: AppIcon.bookmark),
259+
_menuListRowButton(
260+
'Bookmark',
261+
icon: AppIcon.bookmark,
262+
isEnable: true,
263+
onPressed: () {
264+
Navigator.push(context, BookmarkPage.getRoute());
265+
},
266+
),
259267
_menuListRowButton('Moments', icon: AppIcon.moments),
260268
_menuListRowButton('Fwitter ads', icon: AppIcon.twitterAds),
261269
Divider(),

lib/widgets/tweet/widgets/tweetBottomSheet.dart

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ class TweetBottomSheet {
483483
builder: (context) {
484484
return Container(
485485
padding: EdgeInsets.only(top: 5, bottom: 0),
486-
height: 130,
486+
height: 180,
487487
width: context.width,
488488
decoration: BoxDecoration(
489489
color: Theme.of(context).bottomSheetTheme.backgroundColor,
@@ -515,6 +515,22 @@ class TweetBottomSheet {
515515
),
516516
),
517517
),
518+
SizedBox(height: 8),
519+
_widgetBottomSheetRow(
520+
context,
521+
AppIcon.bookmark,
522+
isEnable: true,
523+
text: 'Bookmark',
524+
onPressed: () async {
525+
var state = Provider.of<FeedState>(context, listen: false);
526+
await state.addBookmark(model.key);
527+
Navigator.pop(context);
528+
ScaffoldMessenger.maybeOf(context).showSnackBar(
529+
SnackBar(content: Text("Bookmark saved!!")),
530+
);
531+
},
532+
),
533+
SizedBox(height: 8),
518534
_widgetBottomSheetRow(
519535
context,
520536
AppIcon.link,
@@ -531,6 +547,7 @@ class TweetBottomSheet {
531547
Utility.share(uri.toString(), subject: "Tweet");
532548
},
533549
),
550+
SizedBox(height: 8),
534551
_widgetBottomSheetRow(
535552
context,
536553
AppIcon.image,
@@ -554,7 +571,8 @@ class TweetBottomSheet {
554571
socialMetaTagParameters: socialMetaTagParameters),
555572
);
556573
},
557-
)
574+
),
575+
SizedBox(height: 12),
558576
],
559577
);
560578
}

0 commit comments

Comments
 (0)