Skip to content

Commit f6e2cc4

Browse files
committed
✨: migrate questlist from Cubit to Bloc with updated event handling and state management
1 parent e4493b1 commit f6e2cc4

File tree

8 files changed

+159
-57
lines changed

8 files changed

+159
-57
lines changed

lib/components/kancolle_model/kancolle_parse.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ void kancolleMessageHandle(BuildContext context, WebMessage message) {
3434
case 'api_get_member':
3535
switch (seg[2]) {
3636
case 'questlist':
37-
context.read<QuestlistCubit>().parse(result);
37+
context.read<QuestlistBloc>().add(QuestlistEvent.update(result));
3838
case 'require_info':
3939
//TODO
4040
break;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export 'ndock/ndock_cubit.dart';
22
export 'furniture/furniture_cubit.dart';
33
export 'questlist/questlist_cubit.dart';
4+
export 'questlist/questlist_bloc.dart';
45
export 'slot_item/slot_item_cubit.dart';
56
export 'unsetslot/unsetslot_cubit.dart';
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import 'dart:convert';
2+
3+
import 'package:bloc/bloc.dart';
4+
import 'package:equatable/equatable.dart';
5+
import 'package:freezed_annotation/freezed_annotation.dart';
6+
7+
part 'questlist_event.dart';
8+
part 'questlist_state.dart';
9+
part 'questlist_bloc.freezed.dart';
10+
part 'questlist_bloc.g.dart';
11+
12+
class QuestlistBloc extends Bloc<QuestlistEvent, QuestlistState> {
13+
QuestlistBloc() : super(QuestlistState.initial()) {
14+
on<_EventInitial>((event, emit) {});
15+
on<_EventUpdate>((event, emit) {
16+
final data = jsonDecode(event.data);
17+
data['api_data']['questlist_type'] = 'loaded';
18+
QuestlistStateData questList =
19+
QuestlistStateData.fromJson(data['api_data']);
20+
state.when(
21+
initial: () =>
22+
emit(_Loaded(apiData: questList, sortOrder: SortOrder.noSort)),
23+
loaded: (apiData, sortOrder) {
24+
if (sortOrder != null) {
25+
questList = sort(questList, sortOrder);
26+
} else {
27+
sortOrder = SortOrder.noSort;
28+
}
29+
emit(QuestlistState.loaded(
30+
apiData: questList, sortOrder: sortOrder));
31+
});
32+
});
33+
34+
on<_EventSort>((event, emit) {
35+
if (state is! _Loaded) {
36+
return;
37+
}
38+
var data = sort((state as _Loaded).apiData, event.sort);
39+
emit(QuestlistState.loaded(apiData: data, sortOrder: event.sort));
40+
});
41+
}
42+
43+
QuestlistStateData sort(QuestlistStateData data, SortOrder sort) {
44+
switch (sort) {
45+
case SortOrder.ongoingAsc:
46+
// apiList.sort((a, b) => b.apiState.index.compareTo(a.apiState.index));
47+
data.apiList.sort((a, b) => b.apiState.index.compareTo(a.apiState.index));
48+
49+
break;
50+
case SortOrder.ongoingDesc:
51+
data.apiList.sort((a, b) => a.apiState.index.compareTo(b.apiState.index));
52+
break;
53+
case SortOrder.typeAsc:
54+
data.apiList.sort((a, b) => a.apiCategory.compareTo(b.apiCategory));
55+
break;
56+
case SortOrder.typeDesc:
57+
data.apiList.sort((a, b) => b.apiCategory.compareTo(a.apiCategory));
58+
break;
59+
default:
60+
break;
61+
}
62+
return data;
63+
}
64+
}
Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
import 'dart:convert';
1+
// import 'dart:convert';
22

3-
import 'package:bloc/bloc.dart';
4-
import 'package:freezed_annotation/freezed_annotation.dart';
5-
import 'package:equatable/equatable.dart';
3+
// import 'package:bloc/bloc.dart';
4+
// import 'package:freezed_annotation/freezed_annotation.dart';
5+
// import 'package:equatable/equatable.dart';
66

7-
part 'questlist_state.dart';
8-
part 'questlist_cubit.freezed.dart';
9-
part 'questlist_cubit.g.dart';
7+
// part 'questlist_state.dart';
8+
// part 'questlist_cubit.freezed.dart';
9+
// part 'questlist_cubit.g.dart';
1010

11-
class QuestlistCubit extends Cubit<QuestlistState> {
12-
QuestlistCubit() : super(QuestlistState.initial());
11+
// class QuestlistCubit extends Cubit<QuestlistState> {
12+
// QuestlistCubit() : super(QuestlistState.initial());
1313

14-
void parse(String jsonData) {
15-
final data = jsonDecode(jsonData);
16-
data['api_data']['questlist_type'] = 'loaded';
17-
emit(QuestlistState.fromJson(data['api_data']));
18-
}
19-
}
14+
// void parse(String jsonData) {
15+
// final data = jsonDecode(jsonData);
16+
// data['api_data']['questlist_type'] = 'loaded';
17+
// emit(QuestlistState.fromJson(data['api_data']));
18+
// }
19+
// }
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
part of 'questlist_bloc.dart';
2+
3+
@freezed
4+
class QuestlistEvent with _$QuestlistEvent {
5+
const factory QuestlistEvent.init() = _EventInitial;
6+
const factory QuestlistEvent.update(String data) = _EventUpdate;
7+
const factory QuestlistEvent.sort(SortOrder sort) = _EventSort;
8+
}

lib/components/kancolle_model/kcsapi/get/member/questlist/questlist_state.dart

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
part of 'questlist_cubit.dart';
1+
part of 'questlist_bloc.dart';
22

33
enum QuestState {
44
@JsonValue(1)
@@ -9,27 +9,62 @@ enum QuestState {
99
achieved,
1010
}
1111

12-
@Freezed(unionKey: 'questlist_type', unionValueCase: FreezedUnionCase.pascal)
13-
class QuestlistState with _$QuestlistState implements EquatableMixin{
12+
enum SortOrder {
13+
noSort,
14+
ongoingAsc,
15+
ongoingDesc,
16+
typeAsc,
17+
typeDesc,
18+
}
19+
20+
@freezed
21+
class QuestlistState with _$QuestlistState implements EquatableMixin {
1422
const QuestlistState._();
1523
const factory QuestlistState.initial() = _Initial;
1624

1725
@JsonSerializable(fieldRename: FieldRename.snake)
1826
@FreezedUnionValue('loaded')
1927
const factory QuestlistState.loaded({
28+
required QuestlistStateData apiData,
29+
@Default(SortOrder.noSort) SortOrder? sortOrder,
30+
}) = _Loaded;
31+
32+
factory QuestlistState.fromJson(Map<String, dynamic> json) =>
33+
_$QuestlistStateFromJson(json);
34+
35+
@override
36+
List<Object?> get props => [if (this is _Loaded) (this as _Loaded)];
37+
38+
@override
39+
bool? get stringify => true;
40+
}
41+
42+
@Freezed(
43+
unionKey: 'questlist_type',
44+
unionValueCase: FreezedUnionCase.pascal,
45+
copyWith: true,
46+
makeCollectionsUnmodifiable: false,
47+
equal: false,
48+
)
49+
class QuestlistStateData with _$QuestlistStateData implements EquatableMixin {
50+
const QuestlistStateData._();
51+
52+
@JsonSerializable(fieldRename: FieldRename.snake)
53+
@FreezedUnionValue('loaded')
54+
const factory QuestlistStateData.loaded({
2055
required int apiCount,
2156
required int apiCompletedKind,
2257
required List<Quest> apiList, //fixit
2358
required int apiExecCount,
2459
required List<ApiClist> apiCList, //fixit
2560
required int apiExecType,
26-
}) = _Loaded;
61+
}) = _StateLoaded;
2762

28-
factory QuestlistState.fromJson(Map<String, dynamic> json) =>
29-
_$QuestlistStateFromJson(json);
63+
factory QuestlistStateData.fromJson(Map<String, dynamic> json) =>
64+
_$QuestlistStateDataFromJson(json);
3065

3166
@override
32-
List<Object?> get props => [if(this is _Loaded) (this as _Loaded)];
67+
List<Object?> get props => [if (this is _StateLoaded) (this as _StateLoaded)];
3368

3469
@override
3570
bool? get stringify => true;

lib/main.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class App extends StatelessWidget {
5050
BlocProvider<FurnitureCubit>(create: (context) => FurnitureCubit()),
5151
BlocProvider<UnsetslotCubit>(create: (context) => UnsetslotCubit()),
5252
BlocProvider<Start2GetDataCubit>(create: (context) => Start2GetDataCubit()),
53-
BlocProvider<QuestlistCubit>(create: (context) => QuestlistCubit()),
53+
BlocProvider<QuestlistBloc>(create: (context) => QuestlistBloc()),
5454
],
5555
child: BlocConsumer<GlobalBloc, GlobalState>(
5656
listener: (context, state) {},

lib/screens/questlist.dart

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,25 @@ class QuestlistView extends StatefulWidget {
1111
}
1212

1313
class QuestlistViewState extends State<QuestlistView> {
14-
late int apiCount;
15-
late int apiCompletedKind;
16-
late List<Quest> apiList = [];
17-
late int apiExecCount;
18-
late List<ApiClist> apiCList;
19-
late int apiExecType;
14+
late QuestlistStateData? apiData;
2015

2116
@override
2217
void initState() {
2318
super.initState();
24-
apiList = [];
19+
apiData = context
20+
.read<QuestlistBloc>()
21+
.state
22+
.when(initial: () => null, loaded: (data, _) => data);
2523
}
2624

2725
@override
2826
Widget build(BuildContext context) {
29-
return BlocListener<QuestlistCubit, QuestlistState>(
27+
return BlocListener<QuestlistBloc, QuestlistState>(
3028
listener: (context, state) {
3129
state.when(
3230
initial: () {},
33-
loaded: (apiCount, apiCompletedKind, apiList, apiExecCount,
34-
apiCList, apiExecType) {
35-
this.apiCount = apiCount;
36-
this.apiCompletedKind = apiCompletedKind;
37-
this.apiList = List.from(apiList);
38-
this.apiExecCount = apiExecCount;
39-
this.apiCList = apiCList;
40-
this.apiExecType = apiExecType;
31+
loaded: (apiData, sortOrder) {
32+
this.apiData = apiData;
4133
setState(() {});
4234
},
4335
);
@@ -52,28 +44,30 @@ class QuestlistViewState extends State<QuestlistView> {
5244
wrappedItem: CommandBarButton(
5345
icon: const Icon(FluentIcons.increase_indent),
5446
onPressed: () {
55-
setState(() {
56-
apiList.sort(
57-
(a, b) => b.apiState.index.compareTo(a.apiState.index));
58-
});
47+
context
48+
.read<QuestlistBloc>()
49+
.add(QuestlistEvent.sort(SortOrder.ongoingAsc));
5950
},
6051
),
6152
),
6253
]),
6354
Expanded(
64-
child: ListView.builder(
65-
itemBuilder: (context, index) {
66-
return Tooltip(
67-
message: apiList[index].apiDetail,
68-
child: ListTile.selectable(
69-
leading: Text('月'),
70-
title: Text(apiList[index].apiTitle),
71-
trailing: Text(apiList[index].apiState.toString()),
72-
selected:
73-
apiList[index].apiState != QuestState.unaccepted,
74-
));
75-
},
76-
itemCount: apiList.length)),
55+
child: apiData == null
56+
? const Center()
57+
: ListView.builder(
58+
itemBuilder: (context, index) {
59+
return Tooltip(
60+
message: apiData!.apiList[index].apiDetail,
61+
child: ListTile.selectable(
62+
leading: Text('月'),
63+
title: Text(apiData!.apiList[index].apiTitle),
64+
trailing: Text(
65+
apiData!.apiList[index].apiState.toString()),
66+
selected: apiData!.apiList[index].apiState !=
67+
QuestState.unaccepted,
68+
));
69+
},
70+
itemCount: apiData!.apiList.length))
7771
]));
7872
}
7973
}

0 commit comments

Comments
 (0)