Line data Source code
1 : import 'package:fast_immutable_collections/fast_immutable_collections.dart';
2 : import 'package:flutter/material.dart';
3 : import 'package:freezed_annotation/freezed_annotation.dart';
4 :
5 : import '../../../types.dart';
6 : import '../../app-init/widgets/initial_page.dart';
7 : import '../../auth/utils/login_configs.dart';
8 : import '../../problems/pages/problem_page.dart';
9 : import '../../profile/widgets/profile_page.dart';
10 :
11 : typedef PageDataFromJson = PageData Function(JsonMap json);
12 : typedef PageFromPageData = Page Function(PageData pageData);
13 :
14 : /// [RedFireState.pages] is a list of [PageData] and we use [PageDataConverter]
15 : /// to add a 'type' key to the json during serialisation. The value stored
16 : /// against the 'type' key is used to deserialise the json into the appropriate
17 : /// object.
18 : ///
19 : /// The value stored against the 'type' is the runtimeType of the member.
20 : /// This means serialisation will only work when PageData is a member declared
21 : /// with the @PageDataConverter() annotation.
22 : abstract class PageData {
23 130 : const PageData();
24 : String get typeName;
25 : JsonMap toJson();
26 : }
27 :
28 : // final pageTransformMaps = <String, PageDataTransforms>{};
29 9 : final toMaterialPageMap = <String, PageFromPageData>{};
30 9 : final _fromJsonMap = <String, PageDataFromJson>{};
31 :
32 : // should only be called once on app load
33 : // TODO: create the redfire set without needing to call the function so there
34 : // aren't separate steps that need to be discovered (eg. in tests)
35 : // eg. when creating _fromJsonMap start with a map literal populated with the redfire
36 : // fromJson functions (needs testing in place)
37 3 : void addPageTransforms<T extends RedFireState>(Widget homePage,
38 : ISet<LoginConfig> logins, ISet<PageDataTransforms> transforms) {
39 : // add the transforms from the child package
40 : // pageTransformMaps.addAll(transforms);
41 3 : for (var transform in transforms) {
42 0 : _fromJsonMap[transform.typeName] = transform.fromJson;
43 0 : toMaterialPageMap[transform.typeName] = transform.toMaterialPage;
44 : }
45 :
46 : // add the redfire toMaterialPage transforms
47 8 : toMaterialPageMap[InitialPageData.className] = (_) =>
48 2 : MaterialPage<InitialPage>(
49 : key: const ValueKey(InitialPage),
50 2 : child: InitialPage<T>(homePage, logins));
51 6 : toMaterialPageMap[ProfilePageData.className] = (_) =>
52 0 : MaterialPage<ProfilePage>(
53 0 : key: const ValueKey(ProfilePage), child: ProfilePage<T>());
54 6 : toMaterialPageMap[ProblemPageData.className] =
55 3 : (pageData) => ProblemPage<T>(info: (pageData as ProblemPageData).problem);
56 :
57 : // add the redfire fromJson transforms
58 6 : _fromJsonMap[InitialPageData.className] =
59 2 : (JsonMap json) => InitialPageData.fromJson(json);
60 6 : _fromJsonMap[ProfilePageData.className] =
61 2 : (JsonMap json) => ProfilePageData.fromJson(json);
62 6 : _fromJsonMap[ProblemPageData.className] =
63 2 : (JsonMap json) => ProblemPageData.fromJson(json);
64 : }
65 :
66 : class PageDataTransforms {
67 0 : const PageDataTransforms(
68 : {required this.typeName,
69 : required this.toMaterialPage,
70 : required this.fromJson});
71 : final String typeName;
72 : final PageFromPageData toMaterialPage;
73 : final PageDataFromJson fromJson;
74 : }
75 :
76 : class PageDataConverter implements JsonConverter<PageData, JsonMap> {
77 147 : const PageDataConverter();
78 :
79 1 : @override
80 : PageData fromJson(JsonMap json) {
81 3 : final fromJson = _fromJsonMap[json['type']];
82 : if (fromJson == null) {
83 0 : throw Exception('No entry for \'type\' ${json['type']}');
84 : }
85 1 : return fromJson(json);
86 : }
87 :
88 2 : @override
89 : JsonMap toJson(PageData data) {
90 2 : final json = data.toJson();
91 4 : json['type'] = data.typeName;
92 : return json;
93 : }
94 : }
|