Files

125 lines
3.6 KiB
Dart
Raw Permalink Normal View History

2026-07-27 14:42:23 +02:00
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../core/network/api_exception.dart';
import '../../core/theme/theme_x.dart';
import '../../data/repositories/node_repository.dart';
import 'widgets/connection_form_dialog.dart';
import 'widgets/connections_list.dart';
import 'widgets/no_auth_callout.dart';
import 'widgets/node_identity_form.dart';
import 'widgets/theme_toggle.dart';
class SettingsScreen extends ConsumerWidget {
const SettingsScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return ListView(
padding: const EdgeInsets.all(24),
children: [
_Block(
title: 'Connections',
trailing: TextButton.icon(
onPressed: () => showConnectionFormDialog(context),
icon: const Icon(Icons.add, size: 17),
label: const Text('Add connection'),
),
child: const ConnectionsList(),
),
const SizedBox(height: 22),
_Block(title: 'Node identity', child: const _NodeIdentitySection()),
const SizedBox(height: 22),
_Block(
title: 'Appearance',
child: const Padding(
padding: EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Theme'),
ThemeToggle(),
],
),
),
),
const SizedBox(height: 22),
const NoAuthCallout(),
],
);
}
}
class _NodeIdentitySection extends ConsumerWidget {
const _NodeIdentitySection();
@override
Widget build(BuildContext context, WidgetRef ref) {
final nodeAsync = ref.watch(currentNodeProvider);
return nodeAsync.when(
loading: () => const Padding(
padding: EdgeInsets.all(16),
child: Row(
children: [
SizedBox(width: 14, height: 14, child: CircularProgressIndicator(strokeWidth: 2)),
SizedBox(width: 10),
Text('Contacting node…'),
],
),
),
error: (error, stackTrace) {
final message = error is ApiException ? error.userMessage : error.toString();
return Padding(
padding: const EdgeInsets.all(16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(Icons.error_outline, size: 18, color: context.status.critical),
const SizedBox(width: 10),
Expanded(
child: Text(message, style: context.text.bodyMedium?.copyWith(color: context.status.critical)),
),
],
),
);
},
data: (node) {
if (node == null) {
return const Padding(
padding: EdgeInsets.all(16),
child: Text('No connection selected.'),
);
}
return NodeIdentityForm(node: node);
},
);
}
}
class _Block extends StatelessWidget {
const _Block({required this.title, required this.child, this.trailing});
final String title;
final Widget child;
final Widget? trailing;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(title, style: context.text.titleMedium),
trailing ?? const SizedBox.shrink(),
],
),
const SizedBox(height: 10),
Card(child: child),
],
);
}
}