Skip to content

Commit

Permalink
Merge pull request thunder-app#143 from JulianPaulus/sort-redesign
Browse files Browse the repository at this point in the history
Sort picker redesign
  • Loading branch information
hjiangsu authored Jun 29, 2023
2 parents 05b5270 + 3699472 commit 551d9c1
Show file tree
Hide file tree
Showing 7 changed files with 430 additions and 183 deletions.
219 changes: 91 additions & 128 deletions lib/community/pages/community_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,47 +11,7 @@ import 'package:thunder/community/widgets/community_drawer.dart';
import 'package:thunder/community/widgets/post_card_list.dart';
import 'package:thunder/core/auth/bloc/auth_bloc.dart';
import 'package:thunder/shared/error_message.dart';

class SortTypeItem {
const SortTypeItem({required this.sortType, required this.icon, required this.label});

final SortType sortType;
final IconData icon;
final String label;
}

const sortTypeItems = [
SortTypeItem(
sortType: SortType.hot,
icon: Icons.local_fire_department_rounded,
label: 'Hot',
),
SortTypeItem(
sortType: SortType.active,
icon: Icons.rocket_launch_rounded,
label: 'Active',
),
SortTypeItem(
sortType: SortType.new_,
icon: Icons.auto_awesome_rounded,
label: 'New',
),
// SortTypeItem(
// sortType: SortType.,
// icon: Icons.history_toggle_off_rounded,
// label: 'Old',
// ),
SortTypeItem(
sortType: SortType.mostComments,
icon: Icons.comment_bank_rounded,
label: 'Most Comments',
),
SortTypeItem(
sortType: SortType.newComments,
icon: Icons.add_comment_rounded,
label: 'New Comments',
),
];
import 'package:thunder/shared/sort_picker.dart';

class CommunityPage extends StatefulWidget {
final int? communityId;
Expand All @@ -64,7 +24,8 @@ class CommunityPage extends StatefulWidget {
State<CommunityPage> createState() => _CommunityPageState();
}

class _CommunityPageState extends State<CommunityPage> with AutomaticKeepAliveClientMixin<CommunityPage> {
class _CommunityPageState extends State<CommunityPage>
with AutomaticKeepAliveClientMixin<CommunityPage> {
@override
bool get wantKeepAlive => true;

Expand All @@ -87,7 +48,10 @@ class _CommunityPageState extends State<CommunityPage> with AutomaticKeepAliveCl
if (previousState.sortType != currentState.sortType) {
setState(() {
sortType = currentState.sortType;
sortTypeIcon = sortTypeItems.firstWhere((sortTypeItem) => sortTypeItem.sortType == currentState.sortType).icon;
sortTypeIcon = allSortTypeItems
.firstWhere((sortTypeItem) =>
sortTypeItem.payload == currentState.sortType)
.icon;
});
}
return true;
Expand All @@ -98,7 +62,8 @@ class _CommunityPageState extends State<CommunityPage> with AutomaticKeepAliveCl
content: Text(state.errorMessage ?? 'No error message available'),
behavior: SnackBarBehavior.floating,
);
WidgetsBinding.instance.addPostFrameCallback((timeStamp) => ScaffoldMessenger.of(context).showSnackBar(snackBar));
WidgetsBinding.instance.addPostFrameCallback((timeStamp) =>
ScaffoldMessenger.of(context).showSnackBar(snackBar));
}
},
builder: (context, state) {
Expand All @@ -112,18 +77,33 @@ class _CommunityPageState extends State<CommunityPage> with AutomaticKeepAliveCl
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if ((state.communityId != null || state.communityName != null) && isUserLoggedIn)
if ((state.communityId != null ||
state.communityName != null) &&
isUserLoggedIn)
IconButton(
icon: Icon(
(state.subscribedType == SubscribedType.notSubscribed || state.subscribedType == null) ? Icons.library_add_check_outlined : Icons.library_add_check_rounded,
semanticLabel: (state.subscribedType == SubscribedType.notSubscribed || state.subscribedType == null) ? 'Subscribe' : 'Unsubscribe',
(state.subscribedType ==
SubscribedType.notSubscribed ||
state.subscribedType == null)
? Icons.library_add_check_outlined
: Icons.library_add_check_rounded,
semanticLabel: (state.subscribedType ==
SubscribedType.notSubscribed ||
state.subscribedType == null)
? 'Subscribe'
: 'Unsubscribe',
),
onPressed: () {
HapticFeedback.mediumImpact();
context.read<CommunityBloc>().add(
ChangeCommunitySubsciptionStatusEvent(
communityId: state.communityId!,
follow: (state.subscribedType == null) ? true : (state.subscribedType == SubscribedType.notSubscribed ? true : false),
follow: (state.subscribedType == null)
? true
: (state.subscribedType ==
SubscribedType.notSubscribed
? true
: false),
),
);
},
Expand All @@ -139,29 +119,36 @@ class _CommunityPageState extends State<CommunityPage> with AutomaticKeepAliveCl
)
],
),
drawer: (widget.communityId != null || widget.communityName != null) ? null : const CommunityDrawer(),
floatingActionButton: ((state.communityId != null || widget.communityName != null) && isUserLoggedIn)
? FloatingActionButton(
onPressed: () {
CommunityBloc communityBloc = context.read<CommunityBloc>();

Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return BlocProvider<CommunityBloc>.value(
value: communityBloc,
child: CreatePostPage(communityId: state.communityId!, communityInfo: state.communityInfo),
);
},
drawer: (widget.communityId != null || widget.communityName != null)
? null
: const CommunityDrawer(),
floatingActionButton:
((state.communityId != null || widget.communityName != null) &&
isUserLoggedIn)
? FloatingActionButton(
onPressed: () {
CommunityBloc communityBloc =
context.read<CommunityBloc>();

Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return BlocProvider<CommunityBloc>.value(
value: communityBloc,
child: CreatePostPage(
communityId: state.communityId!,
communityInfo: state.communityInfo),
);
},
),
);
},
child: const Icon(
Icons.add,
semanticLabel: 'Create Post',
),
);
},
child: const Icon(
Icons.add,
semanticLabel: 'Create Post',
),
)
: null,
)
: null,
body: SafeArea(child: _getBody(context, state)),
);
},
Expand All @@ -173,7 +160,10 @@ class _CommunityPageState extends State<CommunityPage> with AutomaticKeepAliveCl
switch (state.status) {
case CommunityStatus.initial:
// communityId and communityName are mutually exclusive - only one of the two should be passed in
context.read<CommunityBloc>().add(GetCommunityPostsEvent(reset: true, communityId: widget.communityId, communityName: widget.communityName));
context.read<CommunityBloc>().add(GetCommunityPostsEvent(
reset: true,
communityId: widget.communityId,
communityName: widget.communityName));
return const Center(child: CircularProgressIndicator());
case CommunityStatus.loading:
return const Center(child: CircularProgressIndicator());
Expand All @@ -192,74 +182,42 @@ class _CommunityPageState extends State<CommunityPage> with AutomaticKeepAliveCl
case CommunityStatus.failure:
return ErrorMessage(
message: state.errorMessage,
action: () => context.read<CommunityBloc>().add(GetCommunityPostsEvent(reset: true, communityId: widget.communityId)),
action: () => context.read<CommunityBloc>().add(
GetCommunityPostsEvent(
reset: true, communityId: widget.communityId)),
actionText: 'Refresh Content',
);
}
}

void showSortBottomSheet(BuildContext context, CommunityState state) {
final theme = Theme.of(context);

showModalBottomSheet<void>(
showDragHandle: true,
showModalBottomSheet(
context: context,
builder: (BuildContext bottomSheetContext) {
return SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 16.0, left: 16.0, right: 16.0),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
'Sort Options',
style: theme.textTheme.titleLarge!.copyWith(),
),
showDragHandle: true,
builder: (builderContext) => SortPicker(
title: 'Sort Options',
onSelect: (selected) {
setState(() {
sortType = selected.payload;
sortTypeIcon = selected.icon;
});

context.read<CommunityBloc>().add(
GetCommunityPostsEvent(
sortType: selected.payload,
reset: true,
listingType: state.communityId != null ? null : state.listingType,
communityId: widget.communityId ?? state.communityId,
),
),
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: sortTypeItems.length,
itemBuilder: (BuildContext itemBuilderContext, int index) {
return ListTile(
title: Text(
sortTypeItems[index].label,
style: theme.textTheme.bodyMedium,
),
leading: Icon(sortTypeItems[index].icon),
onTap: () {
setState(() {
sortType = sortTypeItems[index].sortType;
sortTypeIcon = sortTypeItems[index].icon;
});

context.read<CommunityBloc>().add(
GetCommunityPostsEvent(
sortType: sortTypeItems[index].sortType,
reset: true,
listingType: state.communityId != null ? null : state.listingType,
communityId: widget.communityId ?? state.communityId,
),
);
Navigator.of(context).pop();
},
);
},
),
const SizedBox(height: 16.0),
],
),
);
},
);
},
),
);
}

String getCommunityName(CommunityState state) {
if (state.status == CommunityStatus.initial || state.status == CommunityStatus.loading) {
if (state.status == CommunityStatus.initial ||
state.status == CommunityStatus.loading) {
return '';
}

Expand All @@ -268,6 +226,11 @@ class _CommunityPageState extends State<CommunityPage> with AutomaticKeepAliveCl
return '';
}

return (state.listingType != null) ? (destinations.firstWhere((destination) => destination.listingType == state.listingType).label) : '';
return (state.listingType != null)
? (destinations
.firstWhere(
(destination) => destination.listingType == state.listingType)
.label)
: '';
}
}
26 changes: 16 additions & 10 deletions lib/settings/pages/general_settings_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import 'package:shared_preferences/shared_preferences.dart';

import 'package:thunder/settings/widgets/list_option.dart';
import 'package:thunder/settings/widgets/toggle_option.dart';
import 'package:thunder/shared/sort_picker.dart';
import 'package:thunder/thunder/bloc/thunder_bloc.dart';
import 'package:thunder/utils/bottom_sheet_list_picker.dart';
import 'package:thunder/utils/constants.dart';

class GeneralSettingsPage extends StatefulWidget {
Expand Down Expand Up @@ -211,21 +213,25 @@ class _GeneralSettingsPageState extends State<GeneralSettingsPage> {
),
ListOption(
description: 'Default Feed Type',
value: defaultPostListingType,
options: const [PostListingType.subscribed, PostListingType.all, PostListingType.local],
value: ListPickerItem(label: defaultPostListingType.value, icon: Icons.feed, payload: defaultPostListingType),
options: [
ListPickerItem(icon: Icons.view_list_rounded, label: PostListingType.subscribed.value, payload: PostListingType.subscribed),
ListPickerItem(icon: Icons.home_rounded, label: PostListingType.all.value, payload: PostListingType.all),
ListPickerItem(icon: Icons.grid_view_rounded, label: PostListingType.local.value, payload: PostListingType.local),
],
icon: Icons.feed,
onChanged: (value) => setPreferences('setting_general_default_listing_type', value.name),
labelTransformer: (value) => value.name.capitalize,
onChanged: (value) => setPreferences('setting_general_default_listing_type', value.payload.name),
),
ListOption(
description: 'Default Sort Type',
value: defaultSortType,
options: const [SortType.hot, SortType.active, SortType.new_, SortType.mostComments, SortType.newComments],
value: ListPickerItem(label: defaultSortType.value, icon: Icons.local_fire_department_rounded, payload: defaultSortType),
options: allSortTypeItems,
icon: Icons.sort,
onChanged: (value) => setPreferences('setting_general_default_sort_type', value.name),
labelTransformer: (value) => value.name.capitalize.replaceAll('_', '').replaceAllMapped(RegExp(r'([A-Z])'), (match) {
return ' ${match.group(0)}';
}),
onChanged: (_) {},
customListPicker: SortPicker(title: 'Default Sort Type', onSelect: (value) {
setPreferences('setting_general_default_sort_type', value.payload.name);
},
),
),
],
),
Expand Down
Loading

0 comments on commit 551d9c1

Please sign in to comment.