initial import

This commit is contained in:
2026-07-06 18:01:38 +02:00
commit 8ce435e298
122 changed files with 5392 additions and 0 deletions
+57
View File
@@ -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>);
}
}
+54
View File
@@ -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);
}
}
+85
View File
@@ -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);
}
}
}