Chat UI redesign, splash screen, and onboarding carousel

- Redesign chat screens (both apps) to match Figma: pink theme with
  doodle pattern background, white app bar with centered name and
  chevron back, rose sender bubbles, white receiver bubbles, entry
  banners, and session-ended bottom bar
- Add splash_chat_hebat.png as native Android splash screen with
  Android 12+ support (values-v31)
- Add Flutter splash screen using splash_chat_hebat.png
- Add onboarding carousel (client_app only): 3 pages with 1s
  auto-advance, last page manual "Mulai" button, first-launch only
- Register image assets in both pubspec.yaml files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-17 22:05:15 +08:00
parent 50d31260dc
commit 97d50a8e08
26 changed files with 547 additions and 175 deletions

View File

@@ -8,6 +8,7 @@ import 'features/auth/screens/register_screen.dart';
import 'features/auth/screens/otp_screen.dart';
import 'features/auth/screens/force_register_screen.dart';
import 'features/auth/screens/set_display_name_screen.dart';
import 'features/onboarding/onboarding_screen.dart';
import 'features/splash/splash_screen.dart';
import 'features/home/home_screen.dart';
import 'features/chat/screens/searching_screen.dart';
@@ -25,6 +26,9 @@ class RouterNotifier extends ChangeNotifier {
}
}
/// Cached onboarding status — loaded once at startup, invalidated after onboarding completes
final onboardingDoneProvider = FutureProvider<bool>((ref) => isOnboardingDone());
final routerProvider = Provider<GoRouter>((ref) => buildRouter(ref));
GoRouter buildRouter(Ref ref) {
@@ -36,15 +40,25 @@ GoRouter buildRouter(Ref ref) {
redirect: (context, state) {
final authState = ref.read(authProvider);
final isSplash = state.matchedLocation == '/splash';
final isOnboarding = state.matchedLocation == '/onboarding';
final isAuthRoute = state.matchedLocation.startsWith('/auth') ||
state.matchedLocation == '/welcome';
// Show splash only during initial load — don't redirect away from auth routes
// Show splash only during initial load
if (authState is AsyncLoading) {
if (isSplash || isAuthRoute) return null;
if (isSplash || isAuthRoute || isOnboarding) return null;
return '/splash';
}
// Check onboarding status — must complete before anything else
final onboardingDone = ref.read(onboardingDoneProvider).valueOrNull ?? false;
if (!onboardingDone) {
return isOnboarding ? null : '/onboarding';
}
if (isOnboarding) {
return '/welcome';
}
final data = authState.valueOrNull;
if (data == null) {
// Error state — show login
@@ -64,6 +78,7 @@ GoRouter buildRouter(Ref ref) {
},
routes: [
GoRoute(path: '/splash', builder: (_, __) => const SplashScreen()),
GoRoute(path: '/onboarding', builder: (_, __) => const OnboardingScreen()),
GoRoute(path: '/welcome', builder: (_, __) => const WelcomeScreen()),
GoRoute(path: '/auth/display-name', builder: (_, __) => const DisplayNameScreen()),
GoRoute(path: '/auth/register', builder: (_, __) => const RegisterScreen()),