Skip to content

Commit

Permalink
make widgets reusable
Browse files Browse the repository at this point in the history
  • Loading branch information
wuuzw committed Jan 23, 2021
1 parent 00ec17b commit 34910ce
Show file tree
Hide file tree
Showing 33 changed files with 809 additions and 661 deletions.
2 changes: 2 additions & 0 deletions lib/app/modules/bookmarks/bookmark_controller.dart
@@ -1,4 +1,5 @@
import 'package:flutter_modular/flutter_modular.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:mobx/mobx.dart';

import '../../shared/models/feed_item.dart';
Expand All @@ -11,6 +12,7 @@ class BookmarkController = _BookmarksControllerBase with _$BookmarkController;

abstract class _BookmarksControllerBase with Store {
final BookmarkRepository _bookmarksRepository = Modular.get();
final SlidableController slidableController = SlidableController();

_BookmarksControllerBase();

Expand Down
10 changes: 2 additions & 8 deletions lib/app/modules/bookmarks/bookmark_page.dart
@@ -1,10 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_modular/flutter_modular.dart';

import '../../shared/widgets/bookmark/bookmark_empty_list.dart';
import '../../shared/widgets/bookmark/bookmark_list.dart';
import 'bookmark_controller.dart';
import 'widgets/bookmark_list_body.dart';

class BookmarkPage extends StatefulWidget {
const BookmarkPage({Key key}) : super(key: key);
Expand Down Expand Up @@ -33,11 +31,7 @@ class _BookmarkPageState extends ModularState<BookmarkPage, BookmarkController>
appBar: AppBar(
title: Text('Bookmarks'),
),
body: Observer(
builder: (context) {
return controller.bookmarks.isEmpty ? BookmarkEmptyList() : BookmarkList();
},
),
body: BookmarkListBody(),
);
}
}
40 changes: 40 additions & 0 deletions lib/app/modules/bookmarks/widgets/bookmark_list_body.dart
@@ -0,0 +1,40 @@
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';

import '../../../shared/constants.dart';
import '../../../shared/widgets/empty_indicator.dart';
import '../bookmark_controller.dart';
import 'bookmark_tile.dart';

class BookmarkListBody extends StatelessWidget {
final BookmarkController controller = Modular.get();

@override
Widget build(BuildContext context) {
return Observer(
builder: (context) {
return controller.bookmarks.isEmpty
? EmptyIndicator(
icon: MdiIcons.trayAlert,
message: 'No bookmarks saved',
)
: ListView.builder(
itemCount: controller.bookmarks.length,
padding: const EdgeInsets.symmetric(horizontal: tileHorizontalPadding, vertical: tileVerticalPadding),
itemBuilder: (context, index) {
var bookmark = controller.bookmarks[index];
return BookmarkTile(
bookmark: bookmark,
index: index,
onTap: () {
Modular.to.pushNamed('/item/${bookmark.id}');
},
);
},
);
},
);
}
}
67 changes: 67 additions & 0 deletions lib/app/modules/bookmarks/widgets/bookmark_tile.dart
@@ -0,0 +1,67 @@
import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';

import '../../../shared/constants.dart';
import '../../../shared/models/feed_item.dart';
import '../../../shared/util/url.dart';
import '../../../shared/widgets/tile.dart';
import '../bookmark_controller.dart';

class BookmarkTile extends StatelessWidget {
final int index;
final FeedItem bookmark;
final GestureTapCallback onTap;
final BookmarkController controller = Modular.get();

BookmarkTile({Key key, this.index, this.bookmark, this.onTap}) : super(key: key);

@override
Widget build(BuildContext context) {
return Slidable(
key: Key(bookmark.id.toString()),
controller: controller.slidableController,
actionExtentRatio: actionExtentRatio,
actionPane: SlidableDrawerActionPane(),
child: Tile(
title: Text(bookmark.title),
type: bookmark.type,
user: bookmark.user,
domain: bookmark.domain,
time: bookmark.time,
onTap: onTap,
),
secondaryActions: <Widget>[
IconSlideAction(
caption: 'Delete',
color: Colors.blueGrey,
icon: MdiIcons.bookmarkRemove,
onTap: () {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('Bookmark deleted'),
action: SnackBarAction(
label: 'Undo',
onPressed: () {
controller.undoDelete(index, bookmark);
},
),
),
);

controller.deleteBookmark(bookmark);
},
),
IconSlideAction(
caption: 'Share',
color: Colors.indigo,
icon: MdiIcons.shareVariant,
onTap: () {
UrlUtil().share(title: bookmark.title, url: bookmark.url);
},
),
],
);
}
}
2 changes: 2 additions & 0 deletions lib/app/modules/home/home_controller.dart
@@ -1,4 +1,5 @@
import 'package:flutter_modular/flutter_modular.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:mobx/mobx.dart';

import '../../shared/models/feed_item.dart';
Expand All @@ -14,6 +15,7 @@ class HomeController = _HomeControllerBase with _$HomeController;
abstract class _HomeControllerBase with Store {
final HomeRepository _repository;
final BookmarkRepository _bookmarksRepository = Modular.get();
final SlidableController slidableController = SlidableController();

int _currentPage = 1;
List<FeedItem> feedItems = [];
Expand Down
195 changes: 9 additions & 186 deletions lib/app/modules/home/home_page.dart
@@ -1,18 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:incrementally_loading_listview/incrementally_loading_listview.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:mobx/mobx.dart';

import '../../shared/models/feed_type.dart';
import '../../shared/util/extensions.dart';
import '../../shared/util/url.dart';
import '../../shared/widgets/item_tile/item_tile.dart';
import '../../shared/widgets/loading_indicator.dart';
import 'home_controller.dart';
import 'widgets/dropdown_feed_select.dart';
import 'widgets/feed_bottom_bar.dart';
import 'widgets/feed_list_body.dart';

class HomePage extends StatefulWidget {
const HomePage({Key key}) : super(key: key);
Expand All @@ -24,9 +17,6 @@ class HomePage extends StatefulWidget {
class _HomePageState extends ModularState<HomePage, HomeController> {
ReactionDisposer _disposer;

final ScrollController _scrollController = ScrollController();
final SlidableController _slidableController = SlidableController();

@override
void initState() {
super.initState();
Expand All @@ -37,7 +27,6 @@ class _HomePageState extends ModularState<HomePage, HomeController> {
@override
void dispose() {
_disposer();
_scrollController.dispose();
super.dispose();
}

Expand All @@ -49,178 +38,12 @@ class _HomePageState extends ModularState<HomePage, HomeController> {

@override
Widget build(BuildContext context) {
return Observer(
builder: (context) {
return Scaffold(
appBar: AppBar(
title: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: controller.feedType.name,
icon: Icon(
MdiIcons.chevronDown,
),
onChanged: (newValue) {
controller.feedType = newValue.parseFeedType();
},
items: FeedType.values.map<DropdownMenuItem<String>>((value) {
return DropdownMenuItem<String>(
value: value.name,
child: Text(
value.name.toUpperCase(),
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
);
}).toList(),
),
),
),
),
body: _buildFeedList(),
bottomNavigationBar: BottomAppBar(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Row(
children: <Widget>[
GestureDetector(
child: Text(
'Zone - Hacker News',
),
onTap: () {
_scrollController.animateTo(
0,
curve: Curves.ease,
duration: const Duration(milliseconds: 200),
);
},
),
Spacer(),
IconButton(
icon: Icon(MdiIcons.bookmark),
tooltip: 'Bookmarks',
onPressed: () {
Modular.to.pushNamed('/bookmarks');
},
),
IconButton(
icon: Icon(MdiIcons.refresh),
tooltip: 'Refresh',
onPressed: () {
controller.loadFeedItems();
},
),
],
),
),
),
);
},
return Scaffold(
appBar: AppBar(
title: DropdownFeedSelect(),
),
body: FeedListBody(),
bottomNavigationBar: FeedBottomBar(),
);
}

Widget _buildFeedList() {
final feedItemsFuture = controller.feedItemsFuture;

switch (feedItemsFuture.status) {
case FutureStatus.pending:
return LoadingIndicator();
case FutureStatus.fulfilled:
return RefreshIndicator(
onRefresh: () async {
await controller.loadFeedItems();
},
child: IncrementallyLoadingListView(
controller: _scrollController,
loadMoreOffsetFromBottom: 2,
hasMore: () {
return controller.hasNextPage;
},
itemCount: () {
return controller.feedItems.length;
},
loadMore: () async {
await controller.loadNextPage();
},
itemBuilder: (context, index) {
final item = controller.feedItems[index];

if (controller.isLoadingNextPage && index == controller.feedItems.length - 1) {
return LinearProgressIndicator();
}

return Column(
children: [
Slidable(
key: Key(item.id.toString()),
controller: _slidableController,
actionExtentRatio: 0.2,
actionPane: SlidableDrawerActionPane(),
child: ItemTile(
title: item.title,
user: item.user,
points: item.points,
domain: item.domain,
commentsCount: item.commentsCount,
timeAgo: item.timeAgo,
onTap: () {
Modular.to.pushNamed('/item/${item.id}');
},
),
secondaryActions: <Widget>[
IconSlideAction(
caption: 'Bookmark',
color: Colors.deepOrange,
icon: MdiIcons.bookmark,
onTap: () {
if (item.key == null) {
controller.addBookmark(item);
Fluttertoast.showToast(
msg: 'Bookmark added',
);
}
},
),
IconSlideAction(
caption: 'Share',
color: Colors.indigo,
icon: MdiIcons.shareVariant,
onTap: () {
UrlUtil().share(title: item.title, url: item.url);
},
),
],
),
],
);
},
physics: AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.all(2),
),
);
case FutureStatus.rejected:
default:
return Container(
child: Center(
child: Wrap(
direction: Axis.vertical,
spacing: 20,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
Text('Oops something went wrong'),
RaisedButton.icon(
icon: Icon(MdiIcons.refresh),
label: Text('Retry'),
onPressed: () async {
await controller.loadFeedItems();
},
)
],
),
),
);
}
}
}

0 comments on commit 34910ce

Please sign in to comment.