initial commit
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
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),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user