Move welcome message into first-run backend config dialog

Drop the standalone welcome card from the Settings screen and show the
greeting inside the non-dismissible first-run configuration dialog,
noting that OOTT cannot function without a backend installed in the
network.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
rzuasti
2026-06-12 12:33:31 -04:00
co-authored by Claude Opus 4.8
parent 55192d5665
commit 8b2c8e7285
4 changed files with 48 additions and 39 deletions
@@ -163,6 +163,38 @@ class _BackendConfigDialogState extends State<_BackendConfigDialog> {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// First run: the connection isn't configured yet, so greet the
// user and make clear OOTT relies on a backend running in their
// network.
if (!widget.dismissible) ...[
Card(
color: colorScheme.secondaryContainer,
margin: EdgeInsets.zero,
child: Padding(
padding: const EdgeInsets.all(Insets.lg),
child: Row(
children: [
Icon(
Icons.waving_hand_outlined,
color: colorScheme.onSecondaryContainer,
),
const SizedBox(width: Insets.md),
Expanded(
child: Text(
'Welcome to OOTT! Point the app at your servers '
'API to get started. OOTT cannot function without '
'a backend installed in your network.',
style: textTheme.bodyMedium?.copyWith(
color: colorScheme.onSecondaryContainer,
),
),
),
],
),
),
),
const SizedBox(height: Insets.lg),
],
TextFormField(
controller: _baseUrlController,
onChanged: _onConnectionChanged,
-30
View File
@@ -170,40 +170,10 @@ class _SettingsState extends State<Settings> {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final textTheme = Theme.of(context).textTheme;
return SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (_isFirstRun) ...[
Card(
color: colorScheme.secondaryContainer,
child: Padding(
padding: const EdgeInsets.all(Insets.lg),
child: Row(
children: [
Icon(
Icons.waving_hand_outlined,
color: colorScheme.onSecondaryContainer,
),
const SizedBox(width: Insets.md),
Expanded(
child: Text(
'Welcome to OOTT! Point the app at your servers API '
'to get started.',
style: textTheme.bodyMedium?.copyWith(
color: colorScheme.onSecondaryContainer,
),
),
),
],
),
),
),
const SizedBox(height: Insets.lg),
],
_buildConnectionSummary(context),
const SizedBox(height: Insets.lg),
_buildAppSettings(context),
+15 -8
View File
@@ -88,15 +88,22 @@ void main() {
);
});
testWidgets('shows the welcome intro when no server is configured', (
tester,
) async {
await PrefUtil.setValue('base_url', '');
await pumpScreen(tester, const Settings());
await tester.pump(const Duration(milliseconds: 10));
testWidgets(
'shows the welcome intro in the config dialog when no server is configured',
(tester) async {
await PrefUtil.setValue('base_url', '');
await pumpScreen(tester, const Settings());
await tester.pumpAndSettle();
expect(find.textContaining('Welcome to OOTT'), findsOneWidget);
});
// The first-run dialog opens automatically and carries the welcome note.
expect(find.text('Backend configuration'), findsOneWidget);
expect(find.textContaining('Welcome to OOTT'), findsOneWidget);
expect(
find.textContaining('cannot function without a backend'),
findsOneWidget,
);
},
);
testWidgets('hides the welcome intro once a server is configured', (
tester,