Files
buzz/mobile/lib/shared/widgets/onboarding_loading_page.dart
klopez4212 e922dc08ff Unify mobile onboarding and community entry screens (#8687)
## Summary

Use consistent fullscreen screens for identity setup, community
selection, joining, and Add Community. Restore all memberships and open
the selected community; share the community grid with the switcher.

Add QR-first choices, animated link entry with 12px keyboard clearance,
a two-finger double-tap pairing toggle, and the centered reversing bee
loader. Preserve cancellation, Back, and reduced-motion behavior.

Add intentionally omits community creation and Builderlab sign-in: this
route follows sign-in and the existing-community picker.

### Related issue

Related: #8628 (native profile setup). No duplicate fullscreen
onboarding PR found.

### Testing

- Full standard and hosted-authentication mobile suites, static
analysis, and required push checks passed.
- iPhone preview iterated with Kenny; final simulator walkthrough below
uses synthetic data and does not authenticate or save account changes.
- Independent review completed; regressions cover cancellation during
loading, Add recovery after failed/conflicting memberships, retrying
skipped communities, and explicit picker stages.

Walkthrough recorded before the copy and recovery followups:


https://github.com/user-attachments/assets/bfea3ad3-1dde-40c4-8748-44c84226c292

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz>
2026-10-29 16:12:31 +00:00

81 lines
2.8 KiB
Dart

import 'dart:math' show max;
import 'package:flutter/material.dart';
import '../theme/theme.dart';
import 'bee_loading_mark.dart';
/// Centers the loading mark and heading together as one block.
class OnboardingLoadingPage extends StatelessWidget {
const OnboardingLoadingPage({super.key, required this.title, this.onCancel});
final String title;
final VoidCallback? onCancel;
@override
Widget build(BuildContext context) {
final theme = utilitySurfaceThemeData(Theme.of(context));
final safe = MediaQuery.paddingOf(context);
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, _) {
if (!didPop) onCancel?.call();
},
child: Theme(
data: theme,
child: Scaffold(
backgroundColor: theme.colorScheme.surface,
body: Stack(
children: [
Positioned.fill(
child: LayoutBuilder(
builder: (context, bounds) => SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: bounds.maxHeight),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: Grid.sm,
vertical: max(safe.top, safe.bottom) + Grid.sm,
),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Center(child: BeeLoadingMark()),
const SizedBox(height: Grid.sm),
Semantics(
header: true,
namesRoute: true,
child: Text(
title,
textAlign: TextAlign.center,
style: OnboardingTypography.title.copyWith(
color: theme.colorScheme.onSurface,
),
),
),
],
),
),
),
),
),
),
if (onCancel != null)
Positioned(
left: Grid.sm,
right: Grid.sm,
bottom: safe.bottom + Grid.sm,
child: TextButton(
onPressed: onCancel,
child: const Text('Cancel'),
),
),
],
),
),
),
);
}
}