Skip to content

Commit

Permalink
Add year filtering (#511)
Browse files Browse the repository at this point in the history
  • Loading branch information
JAicewizard authored Aug 28, 2024
1 parent b896cee commit 6498699
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 35 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The latest ThaliApp built on Flutter.
### Other commands

- To run in release mode (without debugging capabilities, so the app does not feel slow), use `flutter run --release`.
- If you've modified anything in `lib/models/*` (that uses `json_serializable`) or something that is mocked in tests, renew the generated files with `flutter pub run build_runner build --delete-conflicting-outputs`.
- If you've modified anything in `lib/models/*` (that uses `json_serializable`) or something that is mocked in tests, renew the generated files with `dart run build_runner build --delete-conflicting-outputs`.
- If anything does not work, run `flutter clean` and try again or run `flutter doctor -v` to check whether everything is installed correctly.
- You can run unit and widget tests with `flutter test`. For integration tests (on a real device or simulator) use `flutter test integration_test`.
- Check out the options that can be passed with `--dart-define` in `lib/config.dart` to run the app using tha API of a local server, to enable TOSTI or run the app with the production API.
Expand Down
1 change: 1 addition & 0 deletions lib/api/api_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ abstract class ApiRepository {
int? limit,
int? offset,
String? ordering,
int? year,
});

/// Get the logged in [FullMember].
Expand Down
2 changes: 2 additions & 0 deletions lib/api/concrexit_api_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,7 @@ class ConcrexitApiRepository implements ApiRepository {
int? limit,
int? offset,
String? ordering,
int? year,
}) async {
assert(
ordering == null ||
Expand All @@ -938,6 +939,7 @@ class ConcrexitApiRepository implements ApiRepository {
if (limit != null) 'limit': limit.toString(),
if (offset != null) 'offset': offset.toString(),
if (ordering != null) 'ordering': ordering,
if (year != null) 'starting_year': year.toString(),
},
);

Expand Down
22 changes: 11 additions & 11 deletions lib/blocs/list_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ abstract class ListCubit<F, T, S> extends Cubit<S> {
futuresUp.add(source.moreUp());
futuresDown.add(source.moreDown());
} on ApiException catch (exception) {
_emit(failure(exception.message));
safeEmit(failure(exception.message));
return;
}
}
Expand Down Expand Up @@ -142,9 +142,9 @@ abstract class ListCubit<F, T, S> extends Cubit<S> {
}

if (upResults.isEmpty && downResults.isEmpty) {
_emit(empty(query ?? ''));
safeEmit(empty(query ?? ''));
} else {
_emit(newState(
safeEmit(newState(
resultsUp: upResults,
resultsDown: downResults,
isDoneUp: isDoneUp,
Expand All @@ -164,15 +164,15 @@ abstract class ListCubit<F, T, S> extends Cubit<S> {
return;
}

_emit(loadingDown(oldState));
safeEmit(loadingDown(oldState));

// Get the data in the down direction
List<List<T>> resultsDown = [];
try {
resultsDown =
await Future.wait(sources.map((source) => source.moreDown()));
} on ApiException catch (exception) {
_emit(failure(exception.message));
safeEmit(failure(exception.message));
return;
}

Expand All @@ -188,7 +188,7 @@ abstract class ListCubit<F, T, S> extends Cubit<S> {
}
final totalDownResults = combineDown(downResults, oldState);

_emit(updateDown(oldState, totalDownResults, isDoneDown));
safeEmit(updateDown(oldState, totalDownResults, isDoneDown));
}

/// moreUp loads more data in the up direction. For example when hitting
Expand All @@ -203,14 +203,14 @@ abstract class ListCubit<F, T, S> extends Cubit<S> {
return;
}

_emit(loadingUp(oldState));
safeEmit(loadingUp(oldState));

// Get the data in the down direction
List<List<T>> resultsUp = [];
try {
resultsUp = await Future.wait(sources.map((source) => source.moreUp()));
} on ApiException catch (exception) {
_emit(failure(exception.message));
safeEmit(failure(exception.message));
return;
}

Expand All @@ -227,7 +227,7 @@ abstract class ListCubit<F, T, S> extends Cubit<S> {

final totalUpResults = combineUp(upResults, oldState);

_emit(updateUp(oldState, totalUpResults, isDoneUp));
safeEmit(updateUp(oldState, totalUpResults, isDoneUp));
}

/// Set this cubit's `searchQuery` and load the albums for that query.
Expand All @@ -239,14 +239,14 @@ abstract class ListCubit<F, T, S> extends Cubit<S> {
_searchDebounceTimer?.cancel();
if (query?.isEmpty ?? false) {
/// Don't get results when the query is empty.
_emit(empty(query ?? ''));
safeEmit(empty(query ?? ''));
} else {
_searchDebounceTimer = Timer(Config.searchDebounceTime, load);
}
}
}

void _emit(S state) {
void safeEmit(S state) {
// Since functions cannot be interupted in dart(without await), and isolates
// dont share memory. Thus we know there is no interuption between this check
// and emiting the state
Expand Down
14 changes: 14 additions & 0 deletions lib/blocs/member_list_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ class MemberListCubit extends SingleListCubit<ListMember> {
static const int firstPageSize = 60;
static const int pageSize = 30;

int? year;

@override
Future<ListResponse<ListMember>> getDown(int offset) => api.getMembers(
search: searchQuery,
limit: offset == 0 ? firstPageSize : pageSize,
offset: offset,
year: year,
);

@override
Expand All @@ -31,4 +34,15 @@ class MemberListCubit extends SingleListCubit<ListMember> {
var q =>
ListState.failure(message: 'No members found found for query "$q"'),
};

/// Set this cubit's `searchQuery` and load the albums for that query.
///
/// Use `null` as argument to remove the search query.
void filterYear(int? year) {
if (year != this.year) {
safeEmit(ListState.loading(results: state.results));
this.year = year;
load();
}
}
}
1 change: 1 addition & 0 deletions lib/models/event.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions lib/ui/screens/calendar_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -301,12 +301,12 @@ class CalendarScrollView extends StatelessWidget {
? Icon(
Icons.more_horiz,
size: 50,
color: theme.colorScheme.secondary,
color: theme.colorScheme.primary,
)
: Text(
'SCROLL TO LOAD MORE',
style: theme.textTheme.bodyLarge!.copyWith(
color: theme.colorScheme.secondary,
color: theme.colorScheme.primary,
fontSize: 20,
fontWeight: FontWeight.bold,
),
Expand Down
81 changes: 68 additions & 13 deletions lib/ui/screens/members_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class _MembersScreenState extends State<MembersScreen> {
key: const PageStorageKey('members'),
controller: _controller,
listState: listState,
currentYear: _cubit.year,
setYear: _cubit.filterYear,
);
}
},
Expand Down Expand Up @@ -151,6 +153,8 @@ class MembersSearchDelegate extends SearchDelegate {
key: const PageStorageKey('members-search'),
controller: _controller,
listState: listState,
currentYear: _cubit.year,
setYear: _cubit.filterYear,
);
}
},
Expand All @@ -159,21 +163,65 @@ class MembersSearchDelegate extends SearchDelegate {

@override
Widget buildSuggestions(BuildContext context) {
return BlocBuilder<MemberListCubit, MemberListState>(
bloc: _cubit..search(query),
builder: (context, listState) {
if (listState.hasException) {
return ErrorScrollView(listState.message!);
} else {
return MemberListScrollView(
key: const PageStorageKey('members-search'),
controller: _controller,
listState: listState,
);
}
},
return buildResults(context);
}
}

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
final int? currentYear;
final void Function(int?) setYear;

_SliverAppBarDelegate(this.currentYear, this.setYear);

final double height = 50;
final List<int> list =
List.generate(DateTime.now().year - 2014 + 1, (i) => 2014 + i)
.reversed
.toList();

@override
double get minExtent => height;

@override
double get maxExtent => height;

@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return ListView(
scrollDirection: Axis.horizontal,
primary: false,
children: [
Wrap(
children: [
const Padding(padding: EdgeInsets.all(2.5), child: Stack()),
Padding(
padding: const EdgeInsets.all(5),
child: FilterChip(
selected: null == currentYear,
label: const Text('ALL'),
onSelected: (_) => setYear(null),
),
),
...list.map((year) => Padding(
padding: const EdgeInsets.all(5),
child: FilterChip(
selected: year == currentYear,
label: Text(year.toString()),
onSelected: (_) => setYear(year),
),
)),
const Padding(padding: EdgeInsets.all(2.5), child: Stack()),
],
),
],
);
}

@override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
return oldDelegate.currentYear != currentYear;
}
}

/// A ScrollView that shows a grid of [MemberTile]s.
Expand All @@ -183,11 +231,15 @@ class MembersSearchDelegate extends SearchDelegate {
class MemberListScrollView extends StatelessWidget {
final ScrollController controller;
final MemberListState listState;
final int? currentYear;
final void Function(int?) setYear;

const MemberListScrollView({
super.key,
required this.controller,
required this.listState,
required this.currentYear,
required this.setYear,
});

@override
Expand All @@ -200,6 +252,9 @@ class MemberListScrollView extends StatelessWidget {
parent: AlwaysScrollableScrollPhysics(),
),
slivers: [
SliverPersistentHeader(
delegate: _SliverAppBarDelegate(currentYear, setYear),
),
SliverPadding(
padding: const EdgeInsets.all(8),
sliver: SliverGrid(
Expand Down
16 changes: 8 additions & 8 deletions lib/ui/theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@ import 'package:google_fonts/google_fonts.dart';

const Color magenta = Color(0xFFE62272);

ColorScheme lightColorScheme = const ColorScheme(
ColorScheme lightColorScheme = ColorScheme(
primary: magenta,
onPrimary: Colors.white,
secondary: magenta,
secondary: magenta.withOpacity(0.8),
onSecondary: Colors.white,
surface: Colors.white,
surface: const Color.fromRGBO(255, 255, 255, 1),
surfaceTint: Colors.transparent,
onSurface: Colors.black,
error: Colors.red,
onError: Colors.white,
brightness: Brightness.light,
);

ColorScheme darkColorScheme = const ColorScheme(
ColorScheme darkColorScheme = ColorScheme(
primary: magenta,
onPrimary: Colors.white,
secondary: magenta,
secondary: magenta.withOpacity(0.5),
onSecondary: Colors.white,
surface: Color(0xFF111111),
surfaceContainerLow: Color(0xFF212121),
surface: const Color(0xFF111111),
surfaceTint: Colors.transparent,
surfaceContainerLow: const Color(0xFF212121),
onSurface: Colors.white,
error: Colors.red,
onError: Colors.white,
Expand Down Expand Up @@ -139,7 +139,7 @@ ThemeData darkTheme = ThemeData.from(
colorScheme: darkColorScheme,
textTheme: generatedTextTheme,
).copyWith(
applyElevationOverlayColor: false,
// applyElevationOverlayColor: false,
// TODO: Make text less white.
primaryTextTheme: ThemeData.dark().primaryTextTheme.merge(generatedTextTheme),
elevatedButtonTheme: ElevatedButtonThemeData(style: darkElevatedButtonStyle),
Expand Down
3 changes: 3 additions & 0 deletions test/mocks.mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,7 @@ class MockApiRepository extends _i1.Mock implements _i5.ApiRepository {
int? limit,
int? offset,
String? ordering,
int? year,
}) =>
(super.noSuchMethod(
Invocation.method(
Expand All @@ -1179,6 +1180,7 @@ class MockApiRepository extends _i1.Mock implements _i5.ApiRepository {
#limit: limit,
#offset: offset,
#ordering: ordering,
#year: year,
},
),
returnValue: _i8.Future<_i4.ListResponse<_i4.ListMember>>.value(
Expand All @@ -1192,6 +1194,7 @@ class MockApiRepository extends _i1.Mock implements _i5.ApiRepository {
#limit: limit,
#offset: offset,
#ordering: ordering,
#year: year,
},
),
)),
Expand Down

0 comments on commit 6498699

Please sign in to comment.