Compare commits
4 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b772b39be6 | |||
| 58e79147c7 | |||
| c290c268e8 | |||
| 6b70116a63 |
10 changed files with 82 additions and 106 deletions
|
|
@ -6,7 +6,7 @@ plugins {
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.slrpg.app"
|
namespace = "com.slrpg.app"
|
||||||
compileSdk = 36
|
compileSdk = 35
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
|
@ -21,7 +21,7 @@ android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "com.slrpg.app"
|
applicationId = "com.slrpg.app"
|
||||||
minSdk = flutter.minSdkVersion
|
minSdk = flutter.minSdkVersion
|
||||||
targetSdk = 36
|
targetSdk = 35
|
||||||
versionCode = 1
|
versionCode = 1
|
||||||
versionName = "1.0.0"
|
versionName = "1.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,23 +23,30 @@ void main() async {
|
||||||
DeviceOrientation.portraitDown,
|
DeviceOrientation.portraitDown,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
final notificationService = NotificationService();
|
|
||||||
await notificationService.init();
|
|
||||||
|
|
||||||
final database = AppDatabase();
|
final database = AppDatabase();
|
||||||
|
|
||||||
final authStore = PbAuthStore();
|
final authStore = PbAuthStore();
|
||||||
await authStore.loadFromStorage();
|
await authStore.loadFromStorage();
|
||||||
|
|
||||||
|
final container = ProviderContainer(
|
||||||
|
overrides: [
|
||||||
|
appDatabaseProvider.overrideWithValue(database),
|
||||||
|
apiClientProvider
|
||||||
|
.overrideWith((ref) => ApiClient(authStore: authStore)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
log('Initializing NotificationService...');
|
||||||
|
container.read(notificationServiceProvider).init();
|
||||||
|
} catch (e) {
|
||||||
|
log('Error triggering NotificationService: $e');
|
||||||
|
}
|
||||||
|
|
||||||
log("Auth loaded. Valid? ${authStore.isValid}");
|
log("Auth loaded. Valid? ${authStore.isValid}");
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
ProviderScope(
|
UncontrolledProviderScope(
|
||||||
overrides: [
|
container: container,
|
||||||
appDatabaseProvider.overrideWithValue(database),
|
|
||||||
apiClientProvider
|
|
||||||
.overrideWith((ref) => ApiClient(authStore: authStore)),
|
|
||||||
],
|
|
||||||
child: const SLRPGApp(),
|
child: const SLRPGApp(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,8 @@ class ErrorHandler {
|
||||||
return l10n.errorEntryNotUnique;
|
return l10n.errorEntryNotUnique;
|
||||||
}
|
}
|
||||||
// PocketBase specific error for failed login
|
// PocketBase specific error for failed login
|
||||||
if (e.contains('Failed to authenticate') || e.contains('identity or password')) {
|
if (e.contains('Failed to authenticate') ||
|
||||||
|
e.contains('identity or password')) {
|
||||||
return l10n.errorAuthenticationFailed;
|
return l10n.errorAuthenticationFailed;
|
||||||
}
|
}
|
||||||
return l10n.errorIllegalRequest;
|
return l10n.errorIllegalRequest;
|
||||||
|
|
@ -41,6 +42,7 @@ class ErrorHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void showErrorSnackBar(BuildContext context, Object error) {
|
static void showErrorSnackBar(BuildContext context, Object error) {
|
||||||
|
if (!context.mounted) return;
|
||||||
final scaffoldMessenger = ScaffoldMessenger.of(context);
|
final scaffoldMessenger = ScaffoldMessenger.of(context);
|
||||||
scaffoldMessenger.hideCurrentSnackBar();
|
scaffoldMessenger.hideCurrentSnackBar();
|
||||||
|
|
||||||
|
|
@ -50,8 +52,8 @@ class ErrorHandler {
|
||||||
backgroundColor: AppTheme.errorColor,
|
backgroundColor: AppTheme.errorColor,
|
||||||
behavior: SnackBarBehavior.floating,
|
behavior: SnackBarBehavior.floating,
|
||||||
duration: const Duration(seconds: 4),
|
duration: const Duration(seconds: 4),
|
||||||
dismissDirection: DismissDirection.horizontal, // Easier to swipe away
|
dismissDirection: DismissDirection.horizontal,
|
||||||
margin: const EdgeInsets.fromLTRB(16, 16, 16, 60), // Move it up to not block navigation
|
margin: const EdgeInsets.fromLTRB(16, 16, 16, 60),
|
||||||
action: SnackBarAction(
|
action: SnackBarAction(
|
||||||
label: 'OK',
|
label: 'OK',
|
||||||
textColor: Colors.white,
|
textColor: Colors.white,
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class NotificationService {
|
||||||
tz.initializeTimeZones();
|
tz.initializeTimeZones();
|
||||||
|
|
||||||
const AndroidInitializationSettings initializationSettingsAndroid =
|
const AndroidInitializationSettings initializationSettingsAndroid =
|
||||||
AndroidInitializationSettings('@mipmap/ic_launcher');
|
AndroidInitializationSettings('ic_launcher');
|
||||||
|
|
||||||
const DarwinInitializationSettings initializationSettingsDarwin =
|
const DarwinInitializationSettings initializationSettingsDarwin =
|
||||||
DarwinInitializationSettings(
|
DarwinInitializationSettings(
|
||||||
|
|
@ -47,8 +47,17 @@ class NotificationService {
|
||||||
final androidImplementation =
|
final androidImplementation =
|
||||||
_notifications.resolvePlatformSpecificImplementation<
|
_notifications.resolvePlatformSpecificImplementation<
|
||||||
AndroidFlutterLocalNotificationsPlugin>();
|
AndroidFlutterLocalNotificationsPlugin>();
|
||||||
await androidImplementation?.requestNotificationsPermission();
|
|
||||||
await androidImplementation?.requestExactAlarmsPermission();
|
if (androidImplementation != null) {
|
||||||
|
// Request notification permission (Android 13+)
|
||||||
|
await androidImplementation.requestNotificationsPermission();
|
||||||
|
|
||||||
|
// requestExactAlarmsPermission is typically for SCHEDULE_EXACT_ALARM.
|
||||||
|
// Since we use USE_EXACT_ALARM in the manifest for newer versions,
|
||||||
|
// we only request this if absolutely necessary or on older versions if supported.
|
||||||
|
// On Android 13+, USE_EXACT_ALARM is granted at install time.
|
||||||
|
await androidImplementation.requestExactAlarmsPermission();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -286,19 +286,19 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
|
||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (dialogContext) => AlertDialog(
|
||||||
title: Text(title, style: const TextStyle(color: AppTheme.errorColor)),
|
title: Text(title, style: const TextStyle(color: AppTheme.errorColor)),
|
||||||
content: Text(content),
|
content: Text(content),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(dialogContext),
|
||||||
child: Text(l10n.commonCancel),
|
child: Text(l10n.commonCancel),
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
style:
|
style:
|
||||||
ElevatedButton.styleFrom(backgroundColor: AppTheme.errorColor),
|
ElevatedButton.styleFrom(backgroundColor: AppTheme.errorColor),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(dialogContext);
|
||||||
onConfirm();
|
onConfirm();
|
||||||
},
|
},
|
||||||
child: Text(l10n.commonConfirm),
|
child: Text(l10n.commonConfirm),
|
||||||
|
|
|
||||||
|
|
@ -253,13 +253,13 @@ class _HubScreenState extends ConsumerState<HubScreen> {
|
||||||
|
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (dialogContext) => AlertDialog(
|
||||||
title: Text(l10n.multiplayerTitle),
|
title: Text(l10n.multiplayerTitle),
|
||||||
content: Text(l10n.multiplayerDescription),
|
content: Text(l10n.multiplayerDescription),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(dialogContext);
|
||||||
_showJoinCodeDialog();
|
_showJoinCodeDialog();
|
||||||
},
|
},
|
||||||
child: Text(l10n.multiplayerJoinButton),
|
child: Text(l10n.multiplayerJoinButton),
|
||||||
|
|
@ -268,14 +268,14 @@ class _HubScreenState extends ConsumerState<HubScreen> {
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: AppTheme.primaryColor),
|
backgroundColor: AppTheme.primaryColor),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
Navigator.pop(context);
|
Navigator.pop(dialogContext);
|
||||||
try {
|
try {
|
||||||
final party =
|
final party =
|
||||||
await ref.read(partyRepositoryProvider).createParty();
|
await ref.read(partyRepositoryProvider).createParty();
|
||||||
if (mounted) context.go('/lobby/${party.id}');
|
if (mounted) context.go('/lobby/${party.id}');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
if (mounted) ErrorHandler.showErrorSnackBar(context, e);
|
ErrorHandler.showErrorSnackBar(context, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -293,7 +293,7 @@ class _HubScreenState extends ConsumerState<HubScreen> {
|
||||||
final controller = TextEditingController();
|
final controller = TextEditingController();
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (dialogContext) => AlertDialog(
|
||||||
title: Text(l10n.multiplayerEnterCodeTitle),
|
title: Text(l10n.multiplayerEnterCodeTitle),
|
||||||
content: TextField(
|
content: TextField(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
|
|
@ -305,21 +305,21 @@ class _HubScreenState extends ConsumerState<HubScreen> {
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(dialogContext),
|
||||||
child: Text(l10n.multiplayerCancelAction),
|
child: Text(l10n.multiplayerCancelAction),
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final code = controller.text.trim().toUpperCase();
|
final code = controller.text.trim().toUpperCase();
|
||||||
if (code.isNotEmpty) {
|
if (code.isNotEmpty) {
|
||||||
Navigator.pop(context);
|
Navigator.pop(dialogContext);
|
||||||
try {
|
try {
|
||||||
final party =
|
final party =
|
||||||
await ref.read(partyRepositoryProvider).joinParty(code);
|
await ref.read(partyRepositoryProvider).joinParty(code);
|
||||||
if (mounted) context.go('/lobby/${party.id}');
|
if (mounted) context.go('/lobby/${party.id}');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
if (mounted) ErrorHandler.showErrorSnackBar(context, e);
|
ErrorHandler.showErrorSnackBar(context, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,11 @@ class PartyRepository {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onCancel: () async {
|
onCancel: () async {
|
||||||
await unsubscribe?.call();
|
try {
|
||||||
|
await unsubscribe?.call();
|
||||||
|
} catch (e) {
|
||||||
|
log('Safe ignore: Unsubscribe error (likely already disconnected): $e');
|
||||||
|
}
|
||||||
log('🔌 Unsubscribed from party $partyId');
|
log('🔌 Unsubscribed from party $partyId');
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -120,7 +124,11 @@ class PartyRepository {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onCancel: () async {
|
onCancel: () async {
|
||||||
await unsubscribe?.call();
|
try {
|
||||||
|
await unsubscribe?.call();
|
||||||
|
} catch (e) {
|
||||||
|
log('Safe ignore: Unsubscribe error (likely already disconnected): $e');
|
||||||
|
}
|
||||||
log('🔌 Unsubscribed from party members $partyId');
|
log('🔌 Unsubscribed from party members $partyId');
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import '../../../shared/data/repositories/user_repository.dart';
|
||||||
|
import '../../../core/utils/notification_service.dart';
|
||||||
|
|
||||||
part 'rest_timer_service.g.dart';
|
part 'rest_timer_service.g.dart';
|
||||||
|
|
||||||
|
|
@ -75,12 +77,21 @@ class RestTimer extends _$RestTimer {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void complete() {
|
void complete() async {
|
||||||
cancel();
|
cancel();
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
isActive: false,
|
isActive: false,
|
||||||
remainingSeconds: 0,
|
remainingSeconds: 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final userRepo = ref.read(userRepositoryProvider);
|
||||||
|
final user = await userRepo.getLocalUser();
|
||||||
|
final settings = user?.notificationSettings ?? {};
|
||||||
|
final restEnabled = settings['rest_finished_enabled'] ?? true;
|
||||||
|
|
||||||
|
if (restEnabled) {
|
||||||
|
ref.read(notificationServiceProvider).showRestFinishedNotification();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cancel() {
|
void cancel() {
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,7 @@ class _BattleScreenState extends ConsumerState<BattleScreen> {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
builder: (context) => AlertDialog(
|
builder: (dialogContext) => AlertDialog(
|
||||||
title: Text(l10n.battleRaidComplete),
|
title: Text(l10n.battleRaidComplete),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
|
@ -267,7 +267,7 @@ class _BattleScreenState extends ConsumerState<BattleScreen> {
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
'+$xpEarned XP',
|
'+$xpEarned XP',
|
||||||
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
style: Theme.of(dialogContext).textTheme.headlineMedium?.copyWith(
|
||||||
color: AppTheme.primaryColor,
|
color: AppTheme.primaryColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -276,7 +276,7 @@ class _BattleScreenState extends ConsumerState<BattleScreen> {
|
||||||
actions: [
|
actions: [
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(dialogContext).pop();
|
||||||
context.go('/hub');
|
context.go('/hub');
|
||||||
},
|
},
|
||||||
child: Text(l10n.battleBackToHub),
|
child: Text(l10n.battleBackToHub),
|
||||||
|
|
@ -1079,7 +1079,8 @@ class _BattleScreenState extends ConsumerState<BattleScreen> {
|
||||||
children: [
|
children: [
|
||||||
_InfoBox(
|
_InfoBox(
|
||||||
label: l10n.battleWeight,
|
label: l10n.battleWeight,
|
||||||
value: '${currentSet.targetWeightTotal} kg',
|
value:
|
||||||
|
'${currentSet.targetWeightTotal} ${l10n.unitKg}',
|
||||||
),
|
),
|
||||||
_InfoBox(
|
_InfoBox(
|
||||||
label: l10n.battleReps,
|
label: l10n.battleReps,
|
||||||
|
|
@ -1193,21 +1194,20 @@ class _BattleScreenState extends ConsumerState<BattleScreen> {
|
||||||
void _showAbandonDialog(AppLocalizations l10n) {
|
void _showAbandonDialog(AppLocalizations l10n) {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (dialogContext) => AlertDialog(
|
||||||
title: Text(l10n.battleAbandonTitle),
|
title: Text(l10n.battleAbandonTitle),
|
||||||
content: Text(l10n.battleAbandonBody),
|
content: Text(l10n.battleAbandonBody),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(dialogContext).pop(),
|
||||||
child: Text(l10n.cancelButton),
|
child: Text(l10n.cancelButton),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(dialogContext).pop();
|
||||||
if (widget.partyId != null) {
|
if (widget.partyId != null) {
|
||||||
final userId =
|
final user = await ref.read(userRepositoryProvider).getLocalUser();
|
||||||
(await ref.read(userRepositoryProvider).getLocalUser())
|
final userId = user?.serverId;
|
||||||
?.serverId;
|
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
await ref
|
await ref
|
||||||
.read(partyRepositoryProvider)
|
.read(partyRepositoryProvider)
|
||||||
|
|
|
||||||
|
|
@ -1,60 +1,3 @@
|
||||||
// import 'dart:convert';
|
|
||||||
// import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
||||||
// import 'package:pocketbase/pocketbase.dart';
|
|
||||||
|
|
||||||
// class PbAuthStore extends AuthStore {
|
|
||||||
// final FlutterSecureStorage _storage;
|
|
||||||
// final String _storageKey;
|
|
||||||
|
|
||||||
// PbAuthStore({
|
|
||||||
// FlutterSecureStorage? storage,
|
|
||||||
// String key = 'pb_auth',
|
|
||||||
// }) : _storage = storage ?? const FlutterSecureStorage(),
|
|
||||||
// _storageKey = key,
|
|
||||||
// super();
|
|
||||||
|
|
||||||
// @override
|
|
||||||
// Future<void> save(String newToken, dynamic newRecord) async {
|
|
||||||
// super.save(newToken, newRecord);
|
|
||||||
|
|
||||||
// final encoded = jsonEncode(<String, dynamic>{
|
|
||||||
// 'token': newToken,
|
|
||||||
// 'model': newRecord,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// await _storage.write(key: _storageKey, value: encoded);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @override
|
|
||||||
// void clear() {
|
|
||||||
// super.clear();
|
|
||||||
// _storage.delete(key: _storageKey);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Future<void> loadFromStorage() async {
|
|
||||||
// final raw = await _storage.read(key: _storageKey);
|
|
||||||
// if (raw != null && raw.isNotEmpty) {
|
|
||||||
// try {
|
|
||||||
// final decoded = jsonDecode(raw) as Map<String, dynamic>;
|
|
||||||
// final token = decoded['token'] as String?;
|
|
||||||
// final model = decoded['model'];
|
|
||||||
|
|
||||||
// if (token != null && token.isNotEmpty) {
|
|
||||||
// super.save(token, model);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// } catch (_) {
|
|
||||||
// clear();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const legacyKey = 'auth_token';
|
|
||||||
// final legacyToken = await _storage.read(key: legacyKey);
|
|
||||||
// if (legacyToken != null && legacyToken.isNotEmpty) {
|
|
||||||
// super.save(legacyToken, null);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:pocketbase/pocketbase.dart';
|
import 'package:pocketbase/pocketbase.dart';
|
||||||
|
|
@ -87,7 +30,6 @@ class PbAuthStore extends AuthStore {
|
||||||
await _storage.delete(key: _saveKey);
|
await _storage.delete(key: _saveKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diese Methode rufen wir VOR App-Start auf!
|
|
||||||
Future<void> loadFromStorage() async {
|
Future<void> loadFromStorage() async {
|
||||||
final raw = await _storage.read(key: _saveKey);
|
final raw = await _storage.read(key: _saveKey);
|
||||||
if (raw != null && raw.isNotEmpty) {
|
if (raw != null && raw.isNotEmpty) {
|
||||||
|
|
@ -106,11 +48,8 @@ class PbAuthStore extends AuthStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// super.save schreibt nur in den Speicher (RAM) des AuthStores,
|
|
||||||
// löst aber kein erneutes 'save' (und damit write) aus.
|
|
||||||
super.save(token, model);
|
super.save(token, model);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Daten korrupt? Löschen.
|
|
||||||
await clear();
|
await clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue