Files
PinePods-nix/PinePods-0.8.2/mobile/lib/ui/auth/auth_wrapper.dart
2026-03-03 10:57:43 -05:00

163 lines
4.5 KiB
Dart

// lib/ui/auth/auth_wrapper.dart
import 'package:flutter/material.dart';
import 'package:pinepods_mobile/bloc/settings/settings_bloc.dart';
import 'package:pinepods_mobile/entities/app_settings.dart';
import 'package:pinepods_mobile/ui/auth/pinepods_startup_login.dart';
import 'package:provider/provider.dart';
class AuthWrapper extends StatefulWidget {
final Widget child;
const AuthWrapper({
Key? key,
required this.child,
}) : super(key: key);
@override
State<AuthWrapper> createState() => _AuthWrapperState();
}
class _AuthWrapperState extends State<AuthWrapper> {
bool _hasInitializedTheme = false;
@override
Widget build(BuildContext context) {
return Consumer<SettingsBloc>(
builder: (context, settingsBloc, _) {
return StreamBuilder<AppSettings>(
stream: settingsBloc.settings,
initialData: settingsBloc.currentSettings,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
final settings = snapshot.data!;
// Check if PinePods server is configured
final hasServer = settings.pinepodsServer != null &&
settings.pinepodsServer!.isNotEmpty;
final hasApiKey = settings.pinepodsApiKey != null &&
settings.pinepodsApiKey!.isNotEmpty;
if (hasServer && hasApiKey) {
// User is logged in, fetch theme from server if not already done
if (!_hasInitializedTheme) {
_hasInitializedTheme = true;
// Fetch theme from server on next frame to avoid modifying state during build
WidgetsBinding.instance.addPostFrameCallback((_) {
settingsBloc.fetchThemeFromServer();
});
}
// Show main app
return widget.child;
} else {
// User needs to login, reset theme initialization flag
_hasInitializedTheme = false;
// Show startup login
return PinepodsStartupLogin(
onLoginSuccess: () {
// Force rebuild to check auth state again
// The StreamBuilder will automatically rebuild when settings change
},
);
}
},
);
},
);
}
}
// Alternative version if you want more explicit control
class AuthChecker extends StatefulWidget {
final Widget authenticatedChild;
final Widget? unauthenticatedChild;
const AuthChecker({
Key? key,
required this.authenticatedChild,
this.unauthenticatedChild,
}) : super(key: key);
@override
State<AuthChecker> createState() => _AuthCheckerState();
}
class _AuthCheckerState extends State<AuthChecker> {
bool _isCheckingAuth = true;
bool _isAuthenticated = false;
@override
void initState() {
super.initState();
_checkAuthStatus();
}
void _checkAuthStatus() {
final settingsBloc = Provider.of<SettingsBloc>(context, listen: false);
final settings = settingsBloc.currentSettings;
final hasServer = settings.pinepodsServer != null &&
settings.pinepodsServer!.isNotEmpty;
final hasApiKey = settings.pinepodsApiKey != null &&
settings.pinepodsApiKey!.isNotEmpty;
setState(() {
_isAuthenticated = hasServer && hasApiKey;
_isCheckingAuth = false;
});
}
void _onLoginSuccess() {
setState(() {
_isAuthenticated = true;
});
}
@override
Widget build(BuildContext context) {
if (_isCheckingAuth) {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
if (_isAuthenticated) {
return widget.authenticatedChild;
} else {
return widget.unauthenticatedChild ??
PinepodsStartupLogin(onLoginSuccess: _onLoginSuccess);
}
}
}
// Simple authentication status provider
class AuthStatus extends InheritedWidget {
final bool isAuthenticated;
final VoidCallback? onAuthChanged;
const AuthStatus({
Key? key,
required this.isAuthenticated,
this.onAuthChanged,
required Widget child,
}) : super(key: key, child: child);
static AuthStatus? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<AuthStatus>();
}
@override
bool updateShouldNotify(AuthStatus oldWidget) {
return isAuthenticated != oldWidget.isAuthenticated;
}
}