From 8394a00861418c2eb60410cc6137d6c89db93b88 Mon Sep 17 00:00:00 2001
From: vjrj <vjrj@comunes.org>
Date: Sun, 14 Jan 2024 13:45:42 +0100
Subject: [PATCH] Added v2 new node types

---
 lib/data/models/node.dart               | 38 +----------------
 lib/data/models/node_list_cubit.dart    | 14 ++++++
 lib/data/models/node_list_state.dart    | 35 ++++++++++++++-
 lib/data/models/node_list_state.g.dart  | 57 ++++++++++++++++++-------
 lib/data/models/node_lists_default.dart | 45 +++++++++++++++++++
 lib/data/models/node_manager.dart       | 14 +++++-
 lib/data/models/node_type.dart          |  2 +-
 lib/ui/screens/node_list_page.dart      | 16 +++++++
 8 files changed, 164 insertions(+), 57 deletions(-)
 create mode 100644 lib/data/models/node_lists_default.dart

diff --git a/lib/data/models/node.dart b/lib/data/models/node.dart
index aab95bf6..51da570d 100644
--- a/lib/data/models/node.dart
+++ b/lib/data/models/node.dart
@@ -1,13 +1,10 @@
 import 'package:equatable/equatable.dart';
-import 'package:flutter_dotenv/flutter_dotenv.dart';
 import 'package:json_annotation/json_annotation.dart';
 
-import 'is_json_serializable.dart';
-
 part 'node.g.dart';
 
 @JsonSerializable()
-class Node extends Equatable implements IsJsonSerializable<Node> {
+class Node extends Equatable {
   const Node(
       {required this.url,
       this.latency = 99999,
@@ -35,43 +32,10 @@ class Node extends Equatable implements IsJsonSerializable<Node> {
     return 'node url: $url latency: $latency errors: $errors currentBlock: $currentBlock';
   }
 
-  @override
   Map<String, dynamic> toJson() => _$NodeToJson(this);
 
-  @override
   Node fromJson(Map<String, dynamic> json) => Node.fromJson(json);
 
   @override
   List<Object?> get props => <dynamic>[url];
 }
-
-List<Node> _splitList(String list) =>
-    list.split(' ').map((String url) => Node(url: url)).toList();
-
-List<Node> _readDotNodeConfig(String entry) => _splitList(dotenv.env[entry]!);
-
-List<Node> defaultDuniterNodes = <Node>{
-  ..._readDotNodeConfig('DUNITER_NODES'),
-  ..._splitList(
-      'duniter.pini.fr duniter.g1.pfouque.xyz fania.g1server.net g1.brussels.ovh g1.cgeek.fr g1.computhings.be g1.cuates.net g1.geragc.es g1.madeirawonders.com g1.rendall.fr g1.trentesaux.fr gibraleon.g1server.net vit.fdn.org')
-}.toList();
-
-List<Node> defaultCesiumPlusNodes = <Node>{
-  ..._readDotNodeConfig('CESIUM_PLUS_NODES'),
-  ..._splitList(
-      'https://g1.data.brussels.ovh https://g1.data.e-is.pro https://g1.data.mithril.re https://g1.data.pini.fr https://g1.data.presles.fr https://g1.data.geragc.es')
-}.toList();
-List<Node> defaultGvaNodes = <Node>{
-  ..._readDotNodeConfig('GVA_NODES'),
-  ..._splitList(
-      'https://g1.cuates.net/gva https://g1.madeirawonders.com/gva https://g1.brussels.ovh/gva https://g1.geragc.es/gva https://gva.seeds4c.org/gva')
-}.toList();
-
-// We test local duniter node in dev mode
-/* List<Node> defaultGvaNodes = kReleaseMode
-    ? readDotNodeConfig('GVA_NODES')
-    : <Node>[const Node(url: 'http://localhost:30901/gva/')]
-  ..addAll(readDotNodeConfig('GVA_NODES'));
-// List<Node> defaultGvaNodes = readDotNodeConfig('GVA_NODES');
- : <Node>[const Node(url: 'http://localhost:30901/gva/')]
-  ..addAll(readDotNodeConfig('GVA_NODES')); */
diff --git a/lib/data/models/node_list_cubit.dart b/lib/data/models/node_list_cubit.dart
index b041ae2b..0511e35f 100644
--- a/lib/data/models/node_list_cubit.dart
+++ b/lib/data/models/node_list_cubit.dart
@@ -25,6 +25,10 @@ class NodeListCubit extends HydratedCubit<NodeListState> {
     emit(state.copyWith(duniterNodes: nodes));
   }
 
+  void setDuniterIndexerNodes(List<Node> nodes) {
+    emit(state.copyWith(duniterIndexerNodes: nodes));
+  }
+
   void setCesiumPlusNodes(List<Node> nodes) {
     emit(state.copyWith(cesiumPlusNodes: nodes));
   }
@@ -33,12 +37,20 @@ class NodeListCubit extends HydratedCubit<NodeListState> {
     emit(state.copyWith(gvaNodes: nodes));
   }
 
+  void setEndpointNodes(List<Node> nodes) {
+    emit(state.copyWith(endpointNodes: nodes));
+  }
+
   List<Node> get duniterNodes => state.duniterNodes;
 
   List<Node> get cesiumPlusNodes => state.cesiumPlusNodes;
 
   List<Node> get gvaNodes => state.gvaNodes;
 
+  List<Node> get endpointNodes => state.endpointNodes;
+
+  List<Node> get duniterIndexerNodes => state.duniterIndexerNodes;
+
   @override
   NodeListState? fromJson(Map<String, dynamic> json) =>
       NodeListState.fromJson(json);
@@ -53,6 +65,8 @@ class NodeListCubit extends HydratedCubit<NodeListState> {
         gvaNodes: state.gvaNodes,
         duniterNodes: state.duniterNodes,
         cesiumPlusNodes: state.cesiumPlusNodes,
+        endpointNodes: state.endpointNodes,
+        duniterIndexerNodes: state.duniterIndexerNodes,
         isLoading: state.isLoading));
   }
 }
diff --git a/lib/data/models/node_list_state.dart b/lib/data/models/node_list_state.dart
index a948a771..4fb400fd 100644
--- a/lib/data/models/node_list_state.dart
+++ b/lib/data/models/node_list_state.dart
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
 import 'package:json_annotation/json_annotation.dart';
 
 import 'node.dart';
+import 'node_lists_default.dart';
 
 part 'node_list_state.g.dart';
 
@@ -15,25 +16,55 @@ class NodeListState extends Equatable {
       {List<Node>? duniterNodes,
       List<Node>? cesiumPlusNodes,
       List<Node>? gvaNodes,
+      List<Node>? endpointNodes,
+      List<Node>? duniterIndexerNodes,
       this.currentGvaNode,
       bool? isLoading})
       : duniterNodes = duniterNodes ?? defaultDuniterNodes,
         cesiumPlusNodes = cesiumPlusNodes ?? defaultCesiumPlusNodes,
         gvaNodes = gvaNodes ?? defaultGvaNodes,
+        endpointNodes = endpointNodes ?? defaultEndPointNodes,
+        duniterIndexerNodes = duniterIndexerNodes ?? defaultDuniterIndexerNodes,
         isLoading = isLoading ?? false;
 
   factory NodeListState.fromJson(Map<String, dynamic> json) =>
       _$NodeListStateFromJson(json);
 
+  @JsonKey(fromJson: _nodesFromJson, toJson: _nodesToJson)
   final List<Node> duniterNodes;
+  @JsonKey(fromJson: _nodesFromJson, toJson: _nodesToJson)
   final List<Node> cesiumPlusNodes;
+  @JsonKey(fromJson: _nodesFromJson, toJson: _nodesToJson)
   final List<Node> gvaNodes;
+  @JsonKey(fromJson: _nodesFromJson, toJson: _nodesToJson)
+  final List<Node> endpointNodes;
+  @JsonKey(fromJson: _nodesFromJson, toJson: _nodesToJson)
+  final List<Node> duniterIndexerNodes;
   final bool isLoading;
+  @JsonKey(fromJson: _nodeFromJson, toJson: _nodeToJson)
   final Node? currentGvaNode;
 
   @override
-  List<Object?> get props =>
-      <Object>[duniterNodes, cesiumPlusNodes, gvaNodes, isLoading];
+  List<Object?> get props => <Object>[
+        duniterNodes,
+        cesiumPlusNodes,
+        gvaNodes,
+        endpointNodes,
+        duniterIndexerNodes,
+        isLoading
+      ];
 
   Map<String, dynamic> toJson() => _$NodeListStateToJson(this);
+
+  static Node? _nodeFromJson(Map<String, dynamic>? json) =>
+      json != null ? Node.fromJson(json) : null;
+
+  static Map<String, dynamic>? _nodeToJson(Node? node) => node?.toJson();
+
+  static List<Node> _nodesFromJson(List<dynamic> json) => json
+      .map((dynamic item) => Node.fromJson(item as Map<String, dynamic>))
+      .toList();
+
+  static List<Map<String, dynamic>> _nodesToJson(List<Node> nodes) =>
+      nodes.map((Node item) => item.toJson()).toList();
 }
diff --git a/lib/data/models/node_list_state.g.dart b/lib/data/models/node_list_state.g.dart
index 475f26f0..a5de96b7 100644
--- a/lib/data/models/node_list_state.g.dart
+++ b/lib/data/models/node_list_state.g.dart
@@ -13,6 +13,10 @@ abstract class _$NodeListStateCWProxy {
 
   NodeListState gvaNodes(List<Node>? gvaNodes);
 
+  NodeListState endpointNodes(List<Node>? endpointNodes);
+
+  NodeListState duniterIndexerNodes(List<Node>? duniterIndexerNodes);
+
   NodeListState currentGvaNode(Node? currentGvaNode);
 
   NodeListState isLoading(bool? isLoading);
@@ -27,6 +31,8 @@ abstract class _$NodeListStateCWProxy {
     List<Node>? duniterNodes,
     List<Node>? cesiumPlusNodes,
     List<Node>? gvaNodes,
+    List<Node>? endpointNodes,
+    List<Node>? duniterIndexerNodes,
     Node? currentGvaNode,
     bool? isLoading,
   });
@@ -49,6 +55,14 @@ class _$NodeListStateCWProxyImpl implements _$NodeListStateCWProxy {
   @override
   NodeListState gvaNodes(List<Node>? gvaNodes) => this(gvaNodes: gvaNodes);
 
+  @override
+  NodeListState endpointNodes(List<Node>? endpointNodes) =>
+      this(endpointNodes: endpointNodes);
+
+  @override
+  NodeListState duniterIndexerNodes(List<Node>? duniterIndexerNodes) =>
+      this(duniterIndexerNodes: duniterIndexerNodes);
+
   @override
   NodeListState currentGvaNode(Node? currentGvaNode) =>
       this(currentGvaNode: currentGvaNode);
@@ -68,6 +82,8 @@ class _$NodeListStateCWProxyImpl implements _$NodeListStateCWProxy {
     Object? duniterNodes = const $CopyWithPlaceholder(),
     Object? cesiumPlusNodes = const $CopyWithPlaceholder(),
     Object? gvaNodes = const $CopyWithPlaceholder(),
+    Object? endpointNodes = const $CopyWithPlaceholder(),
+    Object? duniterIndexerNodes = const $CopyWithPlaceholder(),
     Object? currentGvaNode = const $CopyWithPlaceholder(),
     Object? isLoading = const $CopyWithPlaceholder(),
   }) {
@@ -84,6 +100,14 @@ class _$NodeListStateCWProxyImpl implements _$NodeListStateCWProxy {
           ? _value.gvaNodes
           // ignore: cast_nullable_to_non_nullable
           : gvaNodes as List<Node>?,
+      endpointNodes: endpointNodes == const $CopyWithPlaceholder()
+          ? _value.endpointNodes
+          // ignore: cast_nullable_to_non_nullable
+          : endpointNodes as List<Node>?,
+      duniterIndexerNodes: duniterIndexerNodes == const $CopyWithPlaceholder()
+          ? _value.duniterIndexerNodes
+          // ignore: cast_nullable_to_non_nullable
+          : duniterIndexerNodes as List<Node>?,
       currentGvaNode: currentGvaNode == const $CopyWithPlaceholder()
           ? _value.currentGvaNode
           // ignore: cast_nullable_to_non_nullable
@@ -108,26 +132,27 @@ extension $NodeListStateCopyWith on NodeListState {
 
 NodeListState _$NodeListStateFromJson(Map<String, dynamic> json) =>
     NodeListState(
-      duniterNodes: (json['duniterNodes'] as List<dynamic>?)
-          ?.map((e) => Node.fromJson(e as Map<String, dynamic>))
-          .toList(),
-      cesiumPlusNodes: (json['cesiumPlusNodes'] as List<dynamic>?)
-          ?.map((e) => Node.fromJson(e as Map<String, dynamic>))
-          .toList(),
-      gvaNodes: (json['gvaNodes'] as List<dynamic>?)
-          ?.map((e) => Node.fromJson(e as Map<String, dynamic>))
-          .toList(),
-      currentGvaNode: json['currentGvaNode'] == null
-          ? null
-          : Node.fromJson(json['currentGvaNode'] as Map<String, dynamic>),
+      duniterNodes: NodeListState._nodesFromJson(json['duniterNodes'] as List),
+      cesiumPlusNodes:
+          NodeListState._nodesFromJson(json['cesiumPlusNodes'] as List),
+      gvaNodes: NodeListState._nodesFromJson(json['gvaNodes'] as List),
+      endpointNodes:
+          NodeListState._nodesFromJson(json['endpointNodes'] as List),
+      duniterIndexerNodes:
+          NodeListState._nodesFromJson(json['duniterIndexerNodes'] as List),
+      currentGvaNode: NodeListState._nodeFromJson(
+          json['currentGvaNode'] as Map<String, dynamic>?),
       isLoading: json['isLoading'] as bool?,
     );
 
 Map<String, dynamic> _$NodeListStateToJson(NodeListState instance) =>
     <String, dynamic>{
-      'duniterNodes': instance.duniterNodes,
-      'cesiumPlusNodes': instance.cesiumPlusNodes,
-      'gvaNodes': instance.gvaNodes,
+      'duniterNodes': NodeListState._nodesToJson(instance.duniterNodes),
+      'cesiumPlusNodes': NodeListState._nodesToJson(instance.cesiumPlusNodes),
+      'gvaNodes': NodeListState._nodesToJson(instance.gvaNodes),
+      'endpointNodes': NodeListState._nodesToJson(instance.endpointNodes),
+      'duniterIndexerNodes':
+          NodeListState._nodesToJson(instance.duniterIndexerNodes),
       'isLoading': instance.isLoading,
-      'currentGvaNode': instance.currentGvaNode,
+      'currentGvaNode': NodeListState._nodeToJson(instance.currentGvaNode),
     };
diff --git a/lib/data/models/node_lists_default.dart b/lib/data/models/node_lists_default.dart
new file mode 100644
index 00000000..19357972
--- /dev/null
+++ b/lib/data/models/node_lists_default.dart
@@ -0,0 +1,45 @@
+import 'package:flutter/foundation.dart';
+
+import '../../env.dart';
+import 'node.dart';
+
+List<Node> _splitList(String list) =>
+    list.split(' ').map((String url) => Node(url: url)).toList();
+
+List<Node> _readDotNodeConfig(String entry) => _splitList(entry);
+
+List<Node> defaultDuniterNodes = <Node>{
+  ..._readDotNodeConfig(Env.duniterNodes),
+  ..._splitList(
+      'duniter.pini.fr duniter.g1.pfouque.xyz fania.g1server.net g1.brussels.ovh g1.cgeek.fr g1.computhings.be g1.cuates.net g1.geragc.es g1.madeirawonders.com g1.rendall.fr g1.trentesaux.fr gibraleon.g1server.net vit.fdn.org')
+}.toList();
+
+List<Node> defaultCesiumPlusNodes = <Node>{
+  ..._readDotNodeConfig(Env.cesiumPlusNodes),
+  ..._splitList(
+      'https://g1.data.brussels.ovh https://g1.data.e-is.pro https://g1.data.mithril.re https://g1.data.pini.fr https://g1.data.presles.fr https://g1.data.geragc.es')
+}.toList();
+List<Node> defaultGvaNodes = <Node>{
+  ..._readDotNodeConfig(Env.gvaNodes),
+  ..._splitList(
+      'https://g1.cuates.net/gva https://g1.madeirawonders.com/gva https://g1.brussels.ovh/gva https://g1.geragc.es/gva https://gva.seeds4c.org/gva')
+}.toList();
+
+List<Node> defaultEndPointNodes = <Node>{
+  // For doing tests of faulty nodes
+  if (kDebugMode) const Node(url: 'wss://just-testing-a-wrong-node.com/ws'),
+  ..._readDotNodeConfig(Env.endPoints),
+}.toList();
+
+List<Node> defaultDuniterIndexerNodes = <Node>{
+  ..._readDotNodeConfig(Env.duniterIndexerNodes),
+}.toList();
+
+// We test local duniter node in dev mode
+/* List<Node> defaultGvaNodes = kReleaseMode
+    ? readDotNodeConfig('GVA_NODES')
+    : <Node>[const Node(url: 'http://localhost:30901/gva/')]
+  ..addAll(readDotNodeConfig('GVA_NODES'));
+// List<Node> defaultGvaNodes = readDotNodeConfig('GVA_NODES');
+ : <Node>[const Node(url: 'http://localhost:30901/gva/')]
+  ..addAll(readDotNodeConfig('GVA_NODES')); */
diff --git a/lib/data/models/node_manager.dart b/lib/data/models/node_manager.dart
index b8ef08b5..46d4974d 100644
--- a/lib/data/models/node_manager.dart
+++ b/lib/data/models/node_manager.dart
@@ -21,15 +21,21 @@ class NodeManager {
   final List<Node> duniterNodes = <Node>[];
   final List<Node> cesiumPlusNodes = <Node>[];
   final List<Node> gvaNodes = <Node>[];
+  final List<Node> endpointNodes = <Node>[];
+  final List<Node> duniterIndexerNodes = <Node>[];
 
   void loadFromCubit(NodeListCubit cubit) {
     NodeManagerObserver.instance.cubit = cubit;
     duniterNodes.clear();
     cesiumPlusNodes.clear();
     gvaNodes.clear();
+    endpointNodes.clear();
+    duniterIndexerNodes.clear();
     duniterNodes.addAll(cubit.duniterNodes);
     cesiumPlusNodes.addAll(cubit.cesiumPlusNodes);
     gvaNodes.addAll(cubit.gvaNodes);
+    endpointNodes.addAll(cubit.endpointNodes);
+    duniterIndexerNodes.addAll(cubit.duniterIndexerNodes);
   }
 
   void updateNodes(NodeType type, List<Node> newNodes, {bool notify = true}) {
@@ -69,7 +75,11 @@ class NodeManager {
       ? duniterNodes
       : type == NodeType.cesiumPlus
           ? cesiumPlusNodes
-          : gvaNodes;
+          : type == NodeType.endpoint
+              ? endpointNodes
+              : type == NodeType.duniterIndexer
+                  ? duniterIndexerNodes
+                  : gvaNodes;
 
   void addNode(NodeType type, Node node, {bool notify = true}) {
     final List<Node> nodes = _getList(type);
@@ -181,6 +191,8 @@ class NodeManagerObserver {
     cubit.setDuniterNodes(nodeManager.duniterNodes);
     cubit.setCesiumPlusNodes(nodeManager.cesiumPlusNodes);
     cubit.setGvaNodes(nodeManager.gvaNodes);
+    cubit.setEndpointNodes(nodeManager.endpointNodes);
+    cubit.setDuniterIndexerNodes(nodeManager.duniterIndexerNodes);
   }
 
   void setCurrentGvaNode(Node node) => cubit.setCurrentGvaNode(node);
diff --git a/lib/data/models/node_type.dart b/lib/data/models/node_type.dart
index c55a2a7c..acf6534a 100644
--- a/lib/data/models/node_type.dart
+++ b/lib/data/models/node_type.dart
@@ -1 +1 @@
-enum NodeType { duniter, cesiumPlus, gva }
+enum NodeType { duniter, cesiumPlus, gva, endpoint, duniterIndexer }
diff --git a/lib/ui/screens/node_list_page.dart b/lib/ui/screens/node_list_page.dart
index 0a7a2d63..662bf513 100644
--- a/lib/ui/screens/node_list_page.dart
+++ b/lib/ui/screens/node_list_page.dart
@@ -23,6 +23,10 @@ class NodeListPage extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     final NodeListState state = context.watch<NodeListCubit>().state;
+    final List<Node> endPointNodes =
+        filterAndSortNodesByType(state.endpointNodes, NodeType.endpoint);
+    final List<Node> duniterIndexerNodes = filterAndSortNodesByType(
+        state.duniterIndexerNodes, NodeType.duniterIndexer);
     final List<Node> duniterNodes =
         filterAndSortNodesByType(state.duniterNodes, NodeType.duniter);
     final List<Node> cesiumPlusNodes =
@@ -47,6 +51,18 @@ class NodeListPage extends StatelessWidget {
                 child: Column(
                   crossAxisAlignment: CrossAxisAlignment.start,
                   children: <Widget>[
+                    const DebugNodeHeader(type: NodeType.endpoint),
+                    if (endPointNodes.isNotEmpty)
+                      NodeListWidget(
+                          nodes: endPointNodes,
+                          type: NodeType.endpoint,
+                          currentBlock: endPointNodes[0].currentBlock),
+                    const DebugNodeHeader(type: NodeType.duniterIndexer),
+                    if (duniterIndexerNodes.isNotEmpty)
+                      NodeListWidget(
+                          nodes: duniterNodes,
+                          type: NodeType.duniterIndexer,
+                          currentBlock: duniterIndexerNodes[0].currentBlock),
                     const DebugNodeHeader(type: NodeType.gva),
                     if (gvaNodes.isNotEmpty)
                       NodeListWidget(
-- 
GitLab