fix: login

This commit is contained in:
cogwheel0
2025-09-28 20:41:35 +05:30
parent cb86ad8cd2
commit ba1176a181
5 changed files with 68 additions and 17 deletions

View File

@@ -63,6 +63,7 @@ android {
}
getByName("debug") {
// signingConfig = signingConfigs.getByName("debug")
applicationIdSuffix = ".debug"
}
}
}

View File

@@ -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 [];

View File

@@ -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(

View File

@@ -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 {

View File

@@ -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',