iykyk_msn/mobile/lib/core/session_controller.dart

105 lines
3.0 KiB
Dart

import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'api_client.dart';
final sessionProvider = AsyncNotifierProvider<SessionNotifier, SessionData?>(
SessionNotifier.new,
);
class SessionData {
const SessionData({
required this.userId,
required this.email,
this.defaultContextId,
this.selectedContextId,
});
final String userId;
final String email;
final String? defaultContextId;
final String? selectedContextId;
String? get effectiveContextId => selectedContextId ?? defaultContextId;
}
class SessionNotifier extends AsyncNotifier<SessionData?> {
static const _kContext = 'msn_selected_context_id';
@override
Future<SessionData?> build() async {
final storage = ref.read(tokenStorageProvider);
final token = await storage.readToken();
if (token == null || token.isEmpty) return null;
final dio = ref.read(dioProvider);
try {
final res = await dio.get<Map<String, dynamic>>('/api/auth/me');
final id = res.data!['id'] as String;
final email = res.data!['email'] as String;
final prefs = await SharedPreferences.getInstance();
final saved = prefs.getString(_kContext);
final ctxRes = await dio.get<Map<String, dynamic>>('/api/contexts');
final list = ctxRes.data!['contexts'] as List<dynamic>? ?? [];
String? personalId;
for (final c in list) {
final m = c as Map<String, dynamic>;
if (m['kind'] == 'personal') {
personalId = m['id'] as String;
break;
}
}
final def = personalId ?? (list.isNotEmpty ? (list.first as Map)['id'] as String : null);
return SessionData(
userId: id,
email: email,
defaultContextId: def,
selectedContextId: saved ?? def,
);
} on DioException {
await storage.clear();
return null;
}
}
Future<void> applyLogin({
required String userId,
required String email,
String? defaultContextId,
}) async {
final prefs = await SharedPreferences.getInstance();
final saved = prefs.getString(_kContext);
state = AsyncData(
SessionData(
userId: userId,
email: email,
defaultContextId: defaultContextId,
selectedContextId: saved ?? defaultContextId,
),
);
}
Future<void> setSelectedContext(String contextId) async {
final cur = state.value;
if (cur == null) return;
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_kContext, contextId);
state = AsyncData(
SessionData(
userId: cur.userId,
email: cur.email,
defaultContextId: cur.defaultContextId,
selectedContextId: contextId,
),
);
}
Future<void> logout() async {
await ref.read(tokenStorageProvider).clear();
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_kContext);
state = const AsyncData(null);
}
}