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
+1 -1
View File
@@ -31,7 +31,7 @@
## Frontend ## Frontend
- [ ] Add a note on the settings dialog when empty that you need a backend - [x] Add a note on the settings dialog when empty that you need a backend
- [x] On iOS, the buttons in the Settings configure dialog appear on two lines, try to fit them in one - [x] On iOS, the buttons in the Settings configure dialog appear on two lines, try to fit them in one
- [x] Add more themes (Dracula, Nord, Catppuccin Latte, Gruvbox light) - [x] Add more themes (Dracula, Nord, Catppuccin Latte, Gruvbox light)
- [x] Remove the license and notice from the UI, just link to the github pages - [x] Remove the license and notice from the UI, just link to the github pages
@@ -163,6 +163,38 @@ class _BackendConfigDialogState extends State<_BackendConfigDialog> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ 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( TextFormField(
controller: _baseUrlController, controller: _baseUrlController,
onChanged: _onConnectionChanged, onChanged: _onConnectionChanged,
-30
View File
@@ -170,40 +170,10 @@ class _SettingsState extends State<Settings> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final textTheme = Theme.of(context).textTheme;
return SingleChildScrollView( return SingleChildScrollView(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ 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), _buildConnectionSummary(context),
const SizedBox(height: Insets.lg), const SizedBox(height: Insets.lg),
_buildAppSettings(context), _buildAppSettings(context),
+15 -8
View File
@@ -88,15 +88,22 @@ void main() {
); );
}); });
testWidgets('shows the welcome intro when no server is configured', ( testWidgets(
tester, 'shows the welcome intro in the config dialog when no server is configured',
) async { (tester) async {
await PrefUtil.setValue('base_url', ''); await PrefUtil.setValue('base_url', '');
await pumpScreen(tester, const Settings()); await pumpScreen(tester, const Settings());
await tester.pump(const Duration(milliseconds: 10)); 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', ( testWidgets('hides the welcome intro once a server is configured', (
tester, tester,