Skip to content

Commit 16d7614

Browse files
authored
feat: sort order modifier (#160)
* sort preference data * add provider for sort mode * add button for sort mode * wrap scaffold widget with consumer for SortMode * remove context.read and use variable provided by Consumer instead * update test code * fix missing )
1 parent 8e5f037 commit 16d7614

File tree

6 files changed

+93
-22
lines changed

6 files changed

+93
-22
lines changed

client/ios/Runner.xcodeproj/project.pbxproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -536,4 +536,4 @@
536536
/* End XCConfigurationList section */
537537
};
538538
rootObject = 97C146E61CF9000F007C117D /* Project object */;
539-
}
539+
}

client/lib/main.dart

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:flutter/material.dart';
22
import 'package:pr12er/service.dart';
3+
import 'package:pr12er/sort_preference.dart';
34
import 'package:pr12er/view_models/view_model_videos.dart';
45
import 'package:provider/provider.dart';
56

@@ -18,7 +19,10 @@ void main() => runApp(MultiProvider(providers: [
1819
),
1920
ChangeNotifierProvider<FavoriteVideoViewModel>(
2021
create: (context) => FavoriteVideoViewModel(),
21-
)
22+
),
23+
ChangeNotifierProvider(
24+
create: (context) => SortMode(),
25+
),
2226
], child: const MainApp()));
2327

2428
class MainApp extends StatelessWidget {

client/lib/screens/main_screen.dart

+28-19
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:provider/provider.dart';
44

55
import '../protos/pkg/pr12er/messages.pb.dart';
66
import '../service.dart';
7+
import '../sort_preference.dart';
78
import '../widgets/components/custom_app_bar.dart';
89
import '../widgets/components/custom_bottom_navigation_bar.dart';
910
import '../widgets/main/main_screen_favorite_view.dart';
@@ -37,25 +38,33 @@ class _MainScreenState extends State<MainScreen> {
3738
.where((video) => video.hasTitle() && video.hasLink())
3839
.toList();
3940

40-
return Scaffold(
41-
appBar: CustomAppBar(
42-
videoSearchDelegate: videoSearchDelegate,
43-
context: context,
44-
title: appName,
45-
),
46-
body: IndexedStack(
47-
index: _selectedBottomNavIndex,
48-
children: [
49-
MainScreenListView(cleanList: cleanList),
50-
MainScreenFavoriteView(cleanList: cleanList)
51-
],
52-
),
53-
bottomNavigationBar: CustomBottomNavigationBar(
54-
selectedBottomNavIndex: _selectedBottomNavIndex,
55-
onTap: (index) => setState(() {
56-
_selectedBottomNavIndex = index;
57-
videoSearchDelegate.showOnlyBookmarkItems = index == 1;
58-
})));
41+
return Consumer<SortMode>(
42+
builder: (context, sort, _child) => Scaffold(
43+
appBar: CustomAppBar(
44+
videoSearchDelegate: videoSearchDelegate,
45+
context: context,
46+
title: appName,
47+
),
48+
body: IndexedStack(
49+
index: _selectedBottomNavIndex,
50+
children: [
51+
MainScreenListView(
52+
cleanList: sort.isDescOrder
53+
? cleanList
54+
: List.from(cleanList.reversed)),
55+
MainScreenFavoriteView(
56+
cleanList: sort.isDescOrder
57+
? cleanList
58+
: List.from(cleanList.reversed))
59+
],
60+
),
61+
bottomNavigationBar: CustomBottomNavigationBar(
62+
selectedBottomNavIndex: _selectedBottomNavIndex,
63+
onTap: (index) => setState(() {
64+
_selectedBottomNavIndex = index;
65+
videoSearchDelegate.showOnlyBookmarkItems =
66+
index == 1;
67+
}))));
5968
});
6069
}
6170
}

client/lib/sort_preference.dart

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import 'package:flutter/foundation.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:shared_preferences/shared_preferences.dart';
4+
5+
const _sharedPreferenceSortModeKey = "isDescOrder";
6+
7+
class SortMode extends ChangeNotifier {
8+
bool _isDescOrder = false;
9+
10+
bool get isDescOrder {
11+
return _isDescOrder;
12+
}
13+
14+
/// sharedPreferences is only visible for testing.
15+
/// It is used to test isDarkMode is being loaded from SharedPreferences.
16+
@visibleForTesting
17+
Future<SharedPreferences> get sharedPreferences =>
18+
SharedPreferences.getInstance();
19+
20+
void toggleMode() {
21+
_isDescOrder = !_isDescOrder;
22+
SharedPreferences.getInstance().then(
23+
(pref) => pref.setBool(_sharedPreferenceSortModeKey, _isDescOrder));
24+
notifyListeners();
25+
}
26+
27+
// This type should not be a widget(e.g. Icon) because of mockito support...
28+
IconData get icon =>
29+
_isDescOrder ? Icons.vertical_align_top : Icons.vertical_align_bottom;
30+
31+
// This type should not be a widget(e.g. Text) because of mockito support...
32+
String get text => _isDescOrder ? "오름차순으로" : "내림차순으로";
33+
34+
SortMode() {
35+
SharedPreferences.getInstance().then((pref) {
36+
final isDescOrder = pref.getBool(_sharedPreferenceSortModeKey);
37+
if (isDescOrder != null) {
38+
_isDescOrder = isDescOrder;
39+
notifyListeners();
40+
}
41+
});
42+
}
43+
}

client/lib/widgets/components/custom_app_bar.dart

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import 'package:flutter/material.dart';
22
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
33
import 'package:pr12er/custom_theme.dart';
4+
import 'package:pr12er/sort_preference.dart';
45
import 'package:pr12er/widgets/main/report.dart';
56
import 'package:pr12er/widgets/main/video_search_delegate.dart';
67
import 'package:provider/provider.dart';
78

8-
enum VertMenu { themeMode, issueReport }
9+
enum VertMenu { themeMode, sortMode, issueReport }
910

1011
class CustomAppBar extends AppBar {
1112
CustomAppBar({
@@ -36,6 +37,13 @@ class CustomAppBar extends AppBar {
3637
leading: Icon(context.read<CustomTheme>().icon),
3738
title: Text(context.read<CustomTheme>().text))),
3839
const PopupMenuDivider(height: 5),
40+
PopupMenuItem<VertMenu>(
41+
key: const ValueKey("icon-sort-toggle-button"),
42+
value: VertMenu.sortMode,
43+
child: ListTile(
44+
leading: Icon(context.read<SortMode>().icon),
45+
title: Text(context.read<SortMode>().text))),
46+
const PopupMenuDivider(height: 5),
3947
const PopupMenuItem<VertMenu>(
4048
key: ValueKey("popup-menu-item-issue-report"),
4149
value: VertMenu.issueReport,
@@ -50,6 +58,9 @@ class CustomAppBar extends AppBar {
5058
case VertMenu.themeMode:
5159
context.read<CustomTheme>().toggleMode();
5260
break;
61+
case VertMenu.sortMode:
62+
context.read<SortMode>().toggleMode();
63+
break;
5364
case VertMenu.issueReport:
5465
showMaterialModalBottomSheet(
5566
context: context,

client/test/screens/main_screen_with_mocks_test.dart

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:pr12er/custom_theme.dart';
66
import 'package:pr12er/protos/pkg/pr12er/messages.pb.dart';
77
import 'package:pr12er/screens/main_screen.dart';
88
import 'package:pr12er/service.dart';
9+
import 'package:pr12er/sort_preference.dart';
910
import 'package:pr12er/view_models/view_model_videos.dart';
1011
import 'package:provider/provider.dart';
1112

@@ -112,6 +113,9 @@ MultiProvider wrapWithProviders(
112113
ChangeNotifierProvider<CustomTheme>(create: (context) => mockCustomTheme),
113114
ChangeNotifierProvider<FavoriteVideoViewModel>(
114115
create: (context) => mockFavoriteVideoViewModel),
116+
ChangeNotifierProvider<SortMode>(
117+
create: (context) => SortMode(),
118+
)
115119
],
116120
builder: (context, child) => MaterialApp(home: MainScreen()),
117121
);

0 commit comments

Comments
 (0)