Files
AcWeb/ac_web/lib/Widgets/AgentAvailabilityColumn.dart

114 lines
3.4 KiB
Dart

import 'package:ac_web/Api/AcApi.dart';
import 'package:ac_web/Api/Dtos/AgentDto.dart';
import 'package:ac_web/Pages/AgentDetails.dart';
import 'package:ac_web/Widgets/AgentStatusIndicator.dart';
import 'package:ac_web/Widgets/AgentTypeIcons.dart';
import 'package:ac_web/Widgets/AutoRefreshState.dart';
import 'package:flutter/material.dart';
/// Fetches all agents from the AgentsController and lists them with a colored
/// status indicator in front of their name.
class AgentAvailabilityColumn extends StatefulWidget{
const AgentAvailabilityColumn({super.key});
@override
State<AgentAvailabilityColumn> createState() => _AgentAvailabilityColumnState();
}
class _AgentAvailabilityColumnState extends State<AgentAvailabilityColumn>
with AutoRefreshState<AgentAvailabilityColumn> {
late Future<List<AgentDto>> mAgentsFuture;
@override
void initState() {
super.initState();
mAgentsFuture = AcApi.instance.agents.getAgents();
}
/// Reload triggered by the user. Shows the loading indicator again because
/// the user asked for the request and should see that it is running.
void ReloadAgents(){
setState(() {
mAgentsFuture = AcApi.instance.agents.getAgents();
});
}
/// Automatic reload. The agents that are already on screen stay visible
/// while the request runs, the future is only replaced once it succeeded.
@override
Future<void> RefreshData() async {
final List<AgentDto> agents = await AcApi.instance.agents.getAgents();
if (!mounted) {
return;
}
setState(() {
mAgentsFuture = Future<List<AgentDto>>.value(agents);
});
}
@override
Widget build(BuildContext context) {
return FutureBuilder<List<AgentDto>>(
future: mAgentsFuture,
builder: (context, snapshot) {
// Not `connectionState`: a refresh puts the builder back into the
// waiting state although the previous agents are still available, and
// those should stay on screen instead of flashing a spinner.
if (!snapshot.hasData && !snapshot.hasError) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.hasError && !snapshot.hasData) {
return Center(child: Text('Could not load agents: ${snapshot.error}'));
}
// The list of agents fetched from the AgentsController.
final List<AgentDto> agents = snapshot.data ?? <AgentDto>[];
return _buildList(agents);
},
);
}
Widget _buildList(List<AgentDto> agents) {
if (agents.isEmpty) {
return const Center(child: Text("No agents available"));
}
return RefreshIndicator(
onRefresh: () async => ReloadAgents(),
child: ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: agents.length,
itemBuilder: (context, index) {
final AgentDto agent = agents[index];
return ListTile(
leading: AgentStatusIndicator(status: agent.status),
title: Text(agent.name),
subtitle: Text("${agent.type.displayName} - ${agent.status.displayName}"),
trailing: Icon(agent.type.icon),
onTap: () => _openAgent(agent),
);
},
),
);
}
/// Opens a new page that shows all details of the given agent.
void _openAgent(AgentDto agent) {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (context) => AgentDetails(agent: agent),
),
);
}
}