Skip to content

Commit

Permalink
fix: 대회 알람/캘린더 등록시 인덱스 밀림 버그 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
w8385 committed Oct 13, 2024
1 parent 525d863 commit 567f8fb
Show file tree
Hide file tree
Showing 13 changed files with 180 additions and 42 deletions.
Binary file added assets/images/venues/codechef.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/venues/facebook.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/venues/google.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/venues/icpc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/venues/olympiad.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/venues/scpc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/venues/topcoder.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
122 changes: 111 additions & 11 deletions lib/features/contest/bloc/contest_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,17 @@ class ContestBloc extends Bloc<ContestEvent, ContestState> {
_sharedPreferencesRepository = sharedPreferencesRepository,
super(ContestState(
filters: {
ContestVenue.atCoder: true,
ContestVenue.bojOpen: true,
ContestVenue.codeForces: true,
ContestVenue.programmers: true,
ContestVenue.others: true,
ContestVenue.bojOpen: false,
ContestVenue.atCoder: false,
ContestVenue.codeForces: false,
ContestVenue.olympiad: false,
ContestVenue.google: false,
ContestVenue.facebook: false,
ContestVenue.icpc: false,
ContestVenue.scpc: false,
ContestVenue.codeChef: false,
ContestVenue.topCoder: false,
ContestVenue.programmers: false,
},
)) {
on<ContestInit>(_onInit);
Expand All @@ -47,27 +53,66 @@ class ContestBloc extends Bloc<ContestEvent, ContestState> {
emit(state.copyWith(status: ContestStatus.loading));

try {
final filters = state.filters;
for (ContestVenue venue in ContestVenue.allCases) {
filters[venue] =
await _sharedPreferencesRepository.getIsOnContestFilter(
venue: venue.value,
);
}

final result = await _contestRepository.getContests();
final endedContests = result[ContestType.ended];
final ongoingContests = result[ContestType.ongoing];
final upcomingContests = result[ContestType.upcoming];

List<Contest> filteredEndedContests = [];
List<Contest> filteredOngoingContests = [];
List<Contest> filteredUpcomingContests = [];
List<bool> isOnContestNotifications = [];
List<bool> isOnContestCalendars = [];
for (Contest contest in endedContests ?? []) {
if (await _sharedPreferencesRepository.getIsOnContestFilter(
venue: contest.venue,
)) {
continue;
}
filteredEndedContests.add(contest);
}
for (Contest contest in ongoingContests ?? []) {
if (await _sharedPreferencesRepository.getIsOnContestFilter(
venue: contest.venue,
)) {
continue;
}
filteredOngoingContests.add(contest);
}
for (Contest contest in upcomingContests ?? []) {
isOnContestNotifications.add(await _sharedPreferencesRepository
.getIsOnContestNotification(title: contest.name));
isOnContestCalendars.add(await _sharedPreferencesRepository
.getIsOnContestCalendar(title: contest.name));
if (await _sharedPreferencesRepository.getIsOnContestFilter(
venue: contest.venue,
)) {
continue;
}
filteredUpcomingContests.add(contest);
isOnContestNotifications.add(
await _sharedPreferencesRepository.getIsOnContestNotification(
title: contest.name, startTime: contest.startTime.hashCode));
isOnContestCalendars.add(
await _sharedPreferencesRepository.getIsOnContestCalendar(
title: contest.name, startTime: contest.startTime.hashCode));
}

emit(state.copyWith(
status: ContestStatus.success,
filters: filters,
endedContests: endedContests,
ongoingContests: ongoingContests,
upcomingContests: upcomingContests,
isOnNotificationUpcomingContests: isOnContestNotifications,
isOnCalendarUpcomingContests: isOnContestCalendars,
filteredEndedContests: filteredEndedContests,
filteredOngoingContests: filteredOngoingContests,
filteredUpcomingContests: filteredUpcomingContests,
));
} catch (e) {
emit(state.copyWith(status: ContestStatus.failure));
Expand Down Expand Up @@ -99,6 +144,7 @@ class ContestBloc extends Bloc<ContestEvent, ContestState> {
List<bool> isOnNotifications = state.isOnNotificationUpcomingContests;
final isOn = await _sharedPreferencesRepository.getIsOnContestNotification(
title: contest.name,
startTime: contest.startTime.hashCode,
);
final minute =
await _sharedPreferencesRepository.getContestNotificationMinute();
Expand All @@ -118,6 +164,7 @@ class ContestBloc extends Bloc<ContestEvent, ContestState> {
);
await _sharedPreferencesRepository.setIsOnContestNotification(
title: contest.name,
startTime: contest.startTime.hashCode,
isOn: false,
);
isOnNotifications[event.index] = false;
Expand All @@ -133,6 +180,7 @@ class ContestBloc extends Bloc<ContestEvent, ContestState> {
);
await _sharedPreferencesRepository.setIsOnContestNotification(
title: contest.name,
startTime: contest.startTime.hashCode,
isOn: true,
);
isOnNotifications[event.index] = true;
Expand All @@ -152,11 +200,13 @@ class ContestBloc extends Bloc<ContestEvent, ContestState> {
List<bool> isOnCalendar = state.isOnCalendarUpcomingContests;
final isOn = await _sharedPreferencesRepository.getIsOnContestCalendar(
title: contest.name,
startTime: contest.startTime.hashCode,
);

if (isOn) {
await _sharedPreferencesRepository.setIsOnContestCalendar(
title: contest.name,
startTime: contest.startTime.hashCode,
isOn: false,
);
isOnCalendar[event.index] = false;
Expand Down Expand Up @@ -187,6 +237,7 @@ class ContestBloc extends Bloc<ContestEvent, ContestState> {

await _sharedPreferencesRepository.setIsOnContestCalendar(
title: contest.name,
startTime: contest.startTime.hashCode,
isOn: true,
);
isOnCalendar[event.index] = true;
Expand Down Expand Up @@ -214,7 +265,56 @@ class ContestBloc extends Bloc<ContestEvent, ContestState> {

var filters = state.filters;
final current = filters[event.venue] ?? true;
current ? filters[event.venue] = false : filters[event.venue] = true;
emit(state.copyWith(status: ContestStatus.success, filters: filters));
filters[event.venue] = !current;

await _sharedPreferencesRepository.setIsOnContestFilter(
venue: event.venue.value,
isOn: !current,
);

List<Contest> filteredEndedContests = [];
List<Contest> filteredOngoingContests = [];
List<Contest> filteredUpcomingContests = [];
List<bool> isOnContestNotifications = [];
List<bool> isOnContestCalendars = [];
for (Contest contest in state.endedContests) {
if (await _sharedPreferencesRepository.getIsOnContestFilter(
venue: contest.venue,
)) {
continue;
}
filteredEndedContests.add(contest);
}
for (Contest contest in state.ongoingContests) {
if (await _sharedPreferencesRepository.getIsOnContestFilter(
venue: contest.venue,
)) {
continue;
}
filteredOngoingContests.add(contest);
}
for (Contest contest in state.upcomingContests) {
if (await _sharedPreferencesRepository.getIsOnContestFilter(
venue: contest.venue,
)) {
continue;
}
filteredUpcomingContests.add(contest);
isOnContestNotifications.add(
await _sharedPreferencesRepository.getIsOnContestNotification(
title: contest.name, startTime: contest.startTime.hashCode));
isOnContestCalendars.add(
await _sharedPreferencesRepository.getIsOnContestCalendar(
title: contest.name, startTime: contest.startTime.hashCode));
}

emit(state.copyWith(
status: ContestStatus.success,
filters: filters,
isOnNotificationUpcomingContests: isOnContestNotifications,
isOnCalendarUpcomingContests: isOnContestCalendars,
filteredEndedContests: filteredEndedContests,
filteredOngoingContests: filteredOngoingContests,
filteredUpcomingContests: filteredUpcomingContests));
}
}
27 changes: 15 additions & 12 deletions lib/features/contest/bloc/contest_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,15 @@ class ContestState extends Equatable {
final List<bool> isOnNotificationUpcomingContests;
final List<bool> isOnCalendarUpcomingContests;
final Map<ContestVenue, bool> filters;
final List<Contest> filteredEndedContests;
final List<Contest> filteredOngoingContests;
final List<Contest> filteredUpcomingContests;

List<String> get selectedVenues => ContestVenue.allCases
.where((venue) => filters[venue] ?? false)
.map((venue) => venue.value)
.toList();

List<Contest> get filteredEndedContests => endedContests
.where((contest) => selectedVenues.contains(contest.venue))
.toList();

List<Contest> get filteredOngoingContests => ongoingContests
.where((contest) => selectedVenues.contains(contest.venue))
.toList();

List<Contest> get filteredUpcomingContests => upcomingContests
.where((contest) => selectedVenues.contains(contest.venue))
.toList();

const ContestState({
this.status = ContestStatus.initial,
this.currentIndex = 0,
Expand All @@ -47,6 +38,9 @@ class ContestState extends Equatable {
this.upcomingContests = const [],
this.isOnNotificationUpcomingContests = const [],
this.isOnCalendarUpcomingContests = const [],
this.filteredUpcomingContests = const [],
this.filteredOngoingContests = const [],
this.filteredEndedContests = const [],
required this.filters,
});

Expand All @@ -58,6 +52,9 @@ class ContestState extends Equatable {
List<Contest>? upcomingContests,
List<bool>? isOnNotificationUpcomingContests,
List<bool>? isOnCalendarUpcomingContests,
List<Contest>? filteredEndedContests,
List<Contest>? filteredOngoingContests,
List<Contest>? filteredUpcomingContests,
Map<ContestVenue, bool>? filters,
}) {
return ContestState(
Expand All @@ -70,6 +67,12 @@ class ContestState extends Equatable {
this.isOnNotificationUpcomingContests,
isOnCalendarUpcomingContests:
isOnCalendarUpcomingContests ?? this.isOnCalendarUpcomingContests,
filteredEndedContests:
filteredEndedContests ?? this.filteredEndedContests,
filteredOngoingContests:
filteredOngoingContests ?? this.filteredOngoingContests,
filteredUpcomingContests:
filteredUpcomingContests ?? this.filteredUpcomingContests,
filters: filters ?? this.filters,
);
}
Expand Down
22 changes: 17 additions & 5 deletions lib/features/contest_filter/bloc/contest_filter_state.dart
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
part of 'contest_filter_bloc.dart';

enum ContestVenue {
atCoder("AtCoder", "AtCoder"),
bojOpen("BOJ Open", "BOJ Open"),
atCoder("AtCoder", "AtCoder"),
codeForces("Codeforces", "Codeforces"),
programmers("Programmers", "Programmers"),
others("Others", "Others");
olympiad("Olympiad", "Olympiad"),
google("Google", "Google"),
facebook("Facebook", "Facebook"),
icpc("ICPC", "ICPC"),
scpc("SCPC", "SCPC"),
codeChef("CodeChef", "CodeChef"),
topCoder("TopCoder", "TopCoder"),
programmers("Programmers", "Programmers");

const ContestVenue(this.value, this.displayName);

final String value;
final String displayName;

static List<ContestVenue> get allCases => [
ContestVenue.atCoder,
ContestVenue.bojOpen,
ContestVenue.atCoder,
ContestVenue.codeForces,
ContestVenue.olympiad,
ContestVenue.google,
ContestVenue.facebook,
ContestVenue.icpc,
ContestVenue.scpc,
ContestVenue.codeChef,
ContestVenue.topCoder,
ContestVenue.programmers,
ContestVenue.others,
];
}

Expand Down
10 changes: 5 additions & 5 deletions lib/features/contest_filter/screen/contest_filter_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ class _ContestFilterViewState extends State<ContestFilterView> {
context.read<ContestFilterBloc>().state.venues;
final filter =
widget.contestBloc.state.filters[venues[index]] ??
false;
true;
return ElevatedButton(
onPressed: () => widget.contestBloc.add(
ContestFilterTogglePressed(venue: venues[index])),
style: ElevatedButton.styleFrom(
elevation: 0,
backgroundColor: filter
? MySolvedColor.main
: MySolvedColor.disabledButtonBackground,
? MySolvedColor.disabledButtonBackground
: MySolvedColor.main,
padding: EdgeInsets.symmetric(
vertical: 8, horizontal: 12),
shape: RoundedRectangleBorder(
Expand All @@ -84,8 +84,8 @@ class _ContestFilterViewState extends State<ContestFilterView> {
venues[index].displayName,
style: MySolvedTextStyle.body1.copyWith(
color: filter
? MySolvedColor.background
: MySolvedColor.disabledButtonForeground,
? MySolvedColor.disabledButtonForeground
: MySolvedColor.background,
),
),
);
Expand Down
6 changes: 3 additions & 3 deletions packages/apis/boj_api/lib/src/models/boj_contest.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
enum ContestType { ongoing, upcoming, ended }

class Contest {
final String? venue;
final String venue;
final String name;
final String? url;
final DateTime startTime;
Expand All @@ -10,7 +10,7 @@ class Contest {
final String? background;

const Contest({
this.venue,
required this.venue,
required this.name,
this.url,
required this.startTime,
Expand All @@ -21,7 +21,7 @@ class Contest {

factory Contest.fromJson(Map<String, dynamic> json) {
return Contest(
venue: json['venue'],
venue: json['venue'] ?? '',
name: json['name'],
url: json['url'],
startTime: DateTime.parse(json['startTime']),
Expand Down
Loading

0 comments on commit 567f8fb

Please sign in to comment.