initial import
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import '../config/api_config.dart';
|
||||
import '../models/account.dart';
|
||||
import '../models/event.dart';
|
||||
import '../models/event_detail.dart';
|
||||
import '../models/user_info.dart';
|
||||
|
||||
class ApiService {
|
||||
late final Dio _dio;
|
||||
|
||||
ApiService() {
|
||||
_dio = Dio(BaseOptions(
|
||||
baseUrl: ApiConfig.baseUrl,
|
||||
connectTimeout: const Duration(seconds: 10),
|
||||
receiveTimeout: const Duration(seconds: 10),
|
||||
));
|
||||
}
|
||||
|
||||
void setBearerToken(String token) {
|
||||
_dio.interceptors.add(
|
||||
InterceptorsWrapper(
|
||||
onRequest: (options, handler) {
|
||||
options.headers['Authorization'] = 'Bearer $token';
|
||||
return handler.next(options);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void clearBearerToken() {
|
||||
_dio.interceptors.clear();
|
||||
}
|
||||
|
||||
Future<List<Account>> getAccounts() async {
|
||||
final response = await _dio.get('/accounts');
|
||||
return (response.data as List)
|
||||
.map((json) => Account.fromJson(json as Map<String, dynamic>))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<List<Event>> getSchedule(String account) async {
|
||||
final response = await _dio.get('/schedule', queryParameters: {'account': account});
|
||||
return (response.data as List)
|
||||
.map((json) => Event.fromJson(json as Map<String, dynamic>))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<EventDetail> getGameDetail(String gameId, String account) async {
|
||||
final response = await _dio.get('/game/$gameId', queryParameters: {'account': account});
|
||||
return EventDetail.fromJson(response.data as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Future<UserInfo> getUserInfo() async {
|
||||
final response = await _dio.get('/userinfo');
|
||||
return UserInfo.fromJson(response.data as Map<String, dynamic>);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../config/api_config.dart';
|
||||
|
||||
class AuthService {
|
||||
static const String _tokenKey = 'access_token';
|
||||
static const String _accountKey = 'selected_account';
|
||||
|
||||
Future<String?> getStoredToken() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getString(_tokenKey);
|
||||
}
|
||||
|
||||
Future<String?> getStoredAccount() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getString(_accountKey);
|
||||
}
|
||||
|
||||
Future<String?> login() async {
|
||||
final result = await FlutterWebAuth2.authenticate(
|
||||
url: '${ApiConfig.baseUrl}/login?redirect_uri=${Uri.encodeComponent('myice://callback')}',
|
||||
callbackUrlScheme: 'myice',
|
||||
);
|
||||
|
||||
final uri = Uri.parse(result);
|
||||
// Check for authorization errors first
|
||||
final error = uri.queryParameters['error'];
|
||||
if (error != null) {
|
||||
throw Exception('Authorization failed: $error');
|
||||
}
|
||||
// Extract token from fragment (#access_token=...)
|
||||
final fragment = uri.fragment;
|
||||
final params = Uri.splitQueryString(fragment);
|
||||
final token = params['access_token'];
|
||||
|
||||
if (token != null) {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(_tokenKey, token);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
Future<void> setAccount(String account) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(_accountKey, account);
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove(_tokenKey);
|
||||
await prefs.remove(_accountKey);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
import 'dart:convert';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../models/event.dart';
|
||||
|
||||
class ScheduleCacheService {
|
||||
String _eventsKey(String account) => 'cached_events_$account';
|
||||
String _agegroupKey(String account) => 'filters_agegroup_$account';
|
||||
String _subgroupKey(String account) => 'filters_subgroup_$account';
|
||||
String _timestampKey(String account) => 'cached_events_timestamp_$account';
|
||||
|
||||
Future<void> saveEvents(String account, List<Event> events) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final jsonList = events.map((e) => e.toJson()).toList();
|
||||
await prefs.setString(_eventsKey(account), jsonEncode(jsonList));
|
||||
await prefs.setInt(
|
||||
_timestampKey(account),
|
||||
DateTime.now().millisecondsSinceEpoch,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<Event>?> loadEvents(String account) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final jsonString = prefs.getString(_eventsKey(account));
|
||||
if (jsonString == null) return null;
|
||||
try {
|
||||
final jsonList = jsonDecode(jsonString) as List<dynamic>;
|
||||
return jsonList
|
||||
.map((json) => Event.fromJson(json as Map<String, dynamic>))
|
||||
.toList();
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<DateTime?> getLastUpdated(String account) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final timestamp = prefs.getInt(_timestampKey(account));
|
||||
if (timestamp == null) return null;
|
||||
return DateTime.fromMillisecondsSinceEpoch(timestamp);
|
||||
}
|
||||
|
||||
Future<void> saveFilters(
|
||||
String account,
|
||||
String? agegroup,
|
||||
String? subgroup,
|
||||
) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
if (agegroup != null) {
|
||||
await prefs.setString(_agegroupKey(account), agegroup);
|
||||
} else {
|
||||
await prefs.remove(_agegroupKey(account));
|
||||
}
|
||||
if (subgroup != null) {
|
||||
await prefs.setString(_subgroupKey(account), subgroup);
|
||||
} else {
|
||||
await prefs.remove(_subgroupKey(account));
|
||||
}
|
||||
}
|
||||
|
||||
Future<(String?, String?)> loadFilters(String account) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return (
|
||||
prefs.getString(_agegroupKey(account)),
|
||||
prefs.getString(_subgroupKey(account)),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> clearCache(String account) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove(_eventsKey(account));
|
||||
await prefs.remove(_timestampKey(account));
|
||||
await prefs.remove(_agegroupKey(account));
|
||||
await prefs.remove(_subgroupKey(account));
|
||||
}
|
||||
|
||||
Future<void> clearAllCache() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final keys = prefs.getKeys().where((k) => k.startsWith('cached_events_') ||
|
||||
k.startsWith('filters_') ||
|
||||
k.startsWith('cached_events_timestamp_'));
|
||||
for (final key in keys) {
|
||||
await prefs.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user