fix: login
This commit is contained in:
@@ -63,6 +63,7 @@ android {
|
||||
}
|
||||
getByName("debug") {
|
||||
// signingConfig = signingConfigs.getByName("debug")
|
||||
applicationIdSuffix = ".debug"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,6 +431,12 @@ class _ConversationsCacheTimestampNotifier extends Notifier<DateTime?> {
|
||||
|
||||
// Conversation providers - Now using correct OpenWebUI API with caching
|
||||
final conversationsProvider = FutureProvider<List<Conversation>>((ref) async {
|
||||
// Do not fetch protected data until authenticated
|
||||
final authed = ref.read(isAuthenticatedProvider2);
|
||||
if (!authed) {
|
||||
DebugLogger.log('skip-unauthed', scope: 'conversations');
|
||||
return [];
|
||||
}
|
||||
// Check if we have a recent cache (within 5 seconds)
|
||||
final lastFetch = ref.read(_conversationsCacheTimestamp);
|
||||
if (lastFetch != null && DateTime.now().difference(lastFetch).inSeconds < 5) {
|
||||
@@ -1228,6 +1234,11 @@ final webSearchAvailableProvider = Provider<bool>((ref) {
|
||||
|
||||
// Folders provider
|
||||
final foldersProvider = FutureProvider<List<Folder>>((ref) async {
|
||||
// Protected: require authentication
|
||||
if (!ref.read(isAuthenticatedProvider2)) {
|
||||
DebugLogger.log('skip-unauthed', scope: 'folders');
|
||||
return [];
|
||||
}
|
||||
final api = ref.watch(apiServiceProvider);
|
||||
if (api == null) {
|
||||
DebugLogger.warning('api-missing', scope: 'folders');
|
||||
@@ -1253,6 +1264,11 @@ final foldersProvider = FutureProvider<List<Folder>>((ref) async {
|
||||
|
||||
// Files provider
|
||||
final userFilesProvider = FutureProvider<List<FileInfo>>((ref) async {
|
||||
// Protected: require authentication
|
||||
if (!ref.read(isAuthenticatedProvider2)) {
|
||||
DebugLogger.log('skip-unauthed', scope: 'files');
|
||||
return [];
|
||||
}
|
||||
final api = ref.watch(apiServiceProvider);
|
||||
if (api == null) return [];
|
||||
|
||||
@@ -1270,6 +1286,11 @@ final fileContentProvider = FutureProvider.family<String, String>((
|
||||
ref,
|
||||
fileId,
|
||||
) async {
|
||||
// Protected: require authentication
|
||||
if (!ref.read(isAuthenticatedProvider2)) {
|
||||
DebugLogger.log('skip-unauthed', scope: 'files/content');
|
||||
throw Exception('Not authenticated');
|
||||
}
|
||||
final api = ref.watch(apiServiceProvider);
|
||||
if (api == null) throw Exception('No API service available');
|
||||
|
||||
@@ -1288,6 +1309,11 @@ final fileContentProvider = FutureProvider.family<String, String>((
|
||||
|
||||
// Knowledge Base providers
|
||||
final knowledgeBasesProvider = FutureProvider<List<KnowledgeBase>>((ref) async {
|
||||
// Protected: require authentication
|
||||
if (!ref.read(isAuthenticatedProvider2)) {
|
||||
DebugLogger.log('skip-unauthed', scope: 'knowledge');
|
||||
return [];
|
||||
}
|
||||
final api = ref.watch(apiServiceProvider);
|
||||
if (api == null) return [];
|
||||
|
||||
@@ -1302,6 +1328,11 @@ final knowledgeBasesProvider = FutureProvider<List<KnowledgeBase>>((ref) async {
|
||||
|
||||
final knowledgeBaseItemsProvider =
|
||||
FutureProvider.family<List<KnowledgeBaseItem>, String>((ref, kbId) async {
|
||||
// Protected: require authentication
|
||||
if (!ref.read(isAuthenticatedProvider2)) {
|
||||
DebugLogger.log('skip-unauthed', scope: 'knowledge/items');
|
||||
return [];
|
||||
}
|
||||
final api = ref.watch(apiServiceProvider);
|
||||
if (api == null) return [];
|
||||
|
||||
@@ -1322,6 +1353,11 @@ final knowledgeBaseItemsProvider =
|
||||
|
||||
// Audio providers
|
||||
final availableVoicesProvider = FutureProvider<List<String>>((ref) async {
|
||||
// Protected: require authentication
|
||||
if (!ref.read(isAuthenticatedProvider2)) {
|
||||
DebugLogger.log('skip-unauthed', scope: 'voices');
|
||||
return [];
|
||||
}
|
||||
final api = ref.watch(apiServiceProvider);
|
||||
if (api == null) return [];
|
||||
|
||||
|
||||
@@ -60,7 +60,9 @@ class RouterNotifier extends ChangeNotifier {
|
||||
}
|
||||
|
||||
if (activeServerAsync.isLoading) {
|
||||
// Avoid redirect loops by keeping splash during server loading
|
||||
// Avoid redirect loops: do not override explicit auth routes while loading
|
||||
if (_isAuthLocation(location)) return null;
|
||||
// Keep splash during server loading otherwise
|
||||
return location == Routes.splash ? null : Routes.splash;
|
||||
}
|
||||
|
||||
@@ -80,7 +82,9 @@ class RouterNotifier extends ChangeNotifier {
|
||||
final authState = ref.read(authNavigationStateProvider);
|
||||
switch (authState) {
|
||||
case AuthNavigationState.loading:
|
||||
// Keep splash while establishing session
|
||||
// Keep user on auth routes while loading to prevent bounce
|
||||
if (_isAuthLocation(location)) return null;
|
||||
// Otherwise keep splash during session establishment
|
||||
return location == Routes.splash ? null : Routes.splash;
|
||||
case AuthNavigationState.needsLogin:
|
||||
case AuthNavigationState.error:
|
||||
@@ -146,10 +150,9 @@ final goRouterProvider = Provider<GoRouter>((ref) {
|
||||
name: RouteNames.authentication,
|
||||
builder: (context, state) {
|
||||
final config = state.extra;
|
||||
if (config is! ServerConfig) {
|
||||
return const ServerConnectionPage();
|
||||
}
|
||||
return AuthenticationPage(serverConfig: config);
|
||||
return AuthenticationPage(
|
||||
serverConfig: config is ServerConfig ? config : null,
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
|
||||
@@ -33,15 +33,14 @@ class ConnectivityService {
|
||||
bool get isCurrentlyConnected => _lastStatus == ConnectivityStatus.online;
|
||||
|
||||
void _startConnectivityMonitoring() {
|
||||
// Initial check after a brief delay to avoid showing offline during startup
|
||||
Timer(const Duration(milliseconds: 800), () {
|
||||
_checkConnectivity();
|
||||
});
|
||||
|
||||
// Check periodically; interval adapts to recent failures
|
||||
// Initial check after a slightly longer delay to avoid competing with
|
||||
// first-frame work. Start periodic checks only after the first probe.
|
||||
Timer(const Duration(milliseconds: 1200), () async {
|
||||
await _checkConnectivity();
|
||||
_connectivityTimer = Timer.periodic(_interval, (_) {
|
||||
_checkConnectivity();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _checkConnectivity() async {
|
||||
|
||||
@@ -20,9 +20,9 @@ import 'package:conduit/l10n/app_localizations.dart';
|
||||
import '../providers/unified_auth_providers.dart';
|
||||
|
||||
class AuthenticationPage extends ConsumerStatefulWidget {
|
||||
final ServerConfig serverConfig;
|
||||
final ServerConfig? serverConfig;
|
||||
|
||||
const AuthenticationPage({super.key, required this.serverConfig});
|
||||
const AuthenticationPage({super.key, this.serverConfig});
|
||||
|
||||
@override
|
||||
ConsumerState<AuthenticationPage> createState() => _AuthenticationPageState();
|
||||
@@ -234,6 +234,18 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
|
||||
}
|
||||
|
||||
Widget _buildServerStatus() {
|
||||
// Prefer route-provided config; otherwise fall back to active server
|
||||
final activeServerAsync = ref.watch(activeServerProvider);
|
||||
final cfg =
|
||||
widget.serverConfig ??
|
||||
activeServerAsync.maybeWhen(data: (s) => s, orElse: () => null);
|
||||
final hostText = () {
|
||||
try {
|
||||
final url = cfg?.url;
|
||||
if (url != null && url.isNotEmpty) return Uri.parse(url).host;
|
||||
} catch (_) {}
|
||||
return 'Server';
|
||||
}();
|
||||
return ConduitCard(
|
||||
isElevated: false,
|
||||
padding: const EdgeInsets.all(Spacing.lg),
|
||||
@@ -272,7 +284,7 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
|
||||
),
|
||||
const SizedBox(height: Spacing.xs),
|
||||
Text(
|
||||
Uri.parse(widget.serverConfig.url).host,
|
||||
hostText,
|
||||
style: context.conduitTheme.bodySmall?.copyWith(
|
||||
color: context.conduitTheme.textSecondary,
|
||||
fontFamily: 'monospace',
|
||||
|
||||
Reference in New Issue
Block a user