Skip to content
Snippets Groups Projects
Commit e167ce30 authored by vjrj's avatar vjrj
Browse files

Refactor node list widgets

parent 8f684e56
No related branches found
No related tags found
No related merge requests found
...@@ -21,7 +21,7 @@ import '../widgets/fifth_screen/fifth_tutorial.dart'; ...@@ -21,7 +21,7 @@ import '../widgets/fifth_screen/fifth_tutorial.dart';
import '../widgets/fifth_screen/grid_item.dart'; import '../widgets/fifth_screen/grid_item.dart';
import '../widgets/fifth_screen/import_dialog.dart'; import '../widgets/fifth_screen/import_dialog.dart';
import '../widgets/fifth_screen/link_card.dart'; import '../widgets/fifth_screen/link_card.dart';
import '../widgets/fifth_screen/node_info.dart'; import '../widgets/fifth_screen/node_list_card.dart';
import '../widgets/fifth_screen/text_divider.dart'; import '../widgets/fifth_screen/text_divider.dart';
class FifthScreen extends StatefulWidget { class FifthScreen extends StatefulWidget {
...@@ -216,7 +216,7 @@ class _FifthScreenState extends State<FifthScreen> { ...@@ -216,7 +216,7 @@ class _FifthScreenState extends State<FifthScreen> {
}), }),
if (state.expertMode) if (state.expertMode)
const TextDivider(text: 'technical_info_title'), const TextDivider(text: 'technical_info_title'),
if (state.expertMode) const NodeInfoCard(), if (state.expertMode) const NodeListCard(),
const TextDivider(text: 'info_links'), const TextDivider(text: 'info_links'),
if (state.expertMode) if (state.expertMode)
LinkCard( LinkCard(
......
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../data/models/node.dart';
import '../../data/models/node_list_cubit.dart';
import '../../data/models/node_list_state.dart';
import '../../data/models/node_type.dart';
import '../../g1/api.dart';
import '../../g1/no_nodes_exception.dart';
import '../ui_helpers.dart';
import '../widgets/node_list/node_list_widget.dart';
class NodeListPage extends StatelessWidget {
const NodeListPage({super.key});
List<Node> filterAndSortNodesByType(List<Node> nodes, NodeType type) {
nodes.sort(
(Node a, Node b) => a.currentBlock.compareTo(b.currentBlock) * -1);
return nodes;
}
@override
Widget build(BuildContext context) {
final NodeListState state = context.watch<NodeListCubit>().state;
final List<Node> duniterNodes =
filterAndSortNodesByType(state.duniterNodes, NodeType.duniter);
final List<Node> cesiumPlusNodes =
filterAndSortNodesByType(state.cesiumPlusNodes, NodeType.cesiumPlus);
final List<Node> gvaNodes =
filterAndSortNodesByType(state.gvaNodes, NodeType.gva);
return Scaffold(
appBar: AppBar(
title: Text(tr('nodes_tech_info')),
bottom: state.isLoading
? const PreferredSize(
preferredSize: Size.fromHeight(4.0),
child: LinearProgressIndicator(),
)
: null,
),
body: Container(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.9),
child: Scrollbar(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const DebugNodeHeader(type: NodeType.gva),
if (gvaNodes.isNotEmpty)
NodeListWidget(
nodes: gvaNodes,
type: NodeType.gva,
currentBlock: gvaNodes[0].currentBlock),
const DebugNodeHeader(type: NodeType.duniter),
if (duniterNodes.isNotEmpty)
NodeListWidget(
nodes: duniterNodes,
type: NodeType.duniter,
currentBlock: duniterNodes[0].currentBlock),
const DebugNodeHeader(type: NodeType.cesiumPlus),
if (cesiumPlusNodes.isNotEmpty)
NodeListWidget(
nodes: cesiumPlusNodes,
type: NodeType.cesiumPlus,
currentBlock: cesiumPlusNodes[0].currentBlock),
],
),
),
)));
}
}
class DebugNodeHeader extends StatelessWidget {
const DebugNodeHeader({super.key, required this.type});
final NodeType type;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('${capitalize(type.name)} Nodes',
style: const TextStyle(fontSize: 20)),
GestureDetector(
onLongPress: () => _fetchNodes(context, true),
child: IconButton(
icon: const Icon(Icons.refresh),
// Force in all cases
onPressed: () => _fetchNodes(context, true)),
)
],
));
}
void _fetchNodes(BuildContext context, bool force) {
try {
fetchNodes(type, force);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(tr('reloading_nodes',
namedArgs: <String, String>{'type': type.name})),
));
} on NoNodesException {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(tr('no_nodes_found',
namedArgs: <String, String>{'type': type.name})),
));
}
}
}
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../data/models/node_list_cubit.dart';
import '../../../data/models/node_list_state.dart';
import '../../screens/node_list_page.dart';
import '../fifth_screen/info_card.dart';
class NodeListCard extends StatelessWidget {
const NodeListCard({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<NodeListCubit, NodeListState>(
builder: (BuildContext nodeContext, NodeListState state) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute<VoidCallback>(
builder: (BuildContext context) => const NodeListPage()),
);
},
child: InfoCard(
title: tr('nodes_tech_info'), translate: false, icon: Icons.hub));
});
}
}
import 'package:flutter/material.dart';
import '../../../data/models/node.dart';
import '../../../data/models/node_type.dart';
import '../../../g1/g1_helper.dart';
import '../../ui_helpers.dart';
class NodeListWidget extends StatelessWidget {
const NodeListWidget(
{super.key,
required this.nodes,
required this.currentBlock,
required this.type});
final List<Node> nodes;
final int currentBlock;
final NodeType type;
@override
Widget build(BuildContext context) {
return Column(
children: List<Widget>.generate(
nodes.length,
(int index) {
final Node node = nodes[index];
final int wrongNode = wrongNodeDuration.inMicroseconds;
return Theme(
data: Theme.of(context).copyWith(
visualDensity: VisualDensity.compact,
),
child: GestureDetector(
onTap: () => copyToClipboard(
context: context,
uri: node.url,
feedbackText: 'copied_to_clipboard'),
child: ListTile(
dense: true,
title: Text(node.url),
subtitle: node.latency < wrongNode
? Text(
'${type != NodeType.cesiumPlus ? 'Current block: ${node.currentBlock}, ' : 'Current docs: ${node.currentBlock}, '}errors: ${node.errors}, latency (ms): ${node.latency}')
: null,
leading: node.currentBlock == currentBlock &&
node.latency < wrongNode
? const Icon(Icons.check_circle, color: Colors.green)
: node.latency < wrongNode
? const Icon(Icons.run_circle, color: Colors.grey)
: const Icon(Icons.power_off, color: Colors.grey),
)));
},
));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment