yubioath-flutter/lib/oath/state.dart

110 lines
3.4 KiB
Dart
Raw Normal View History

2021-11-19 17:05:57 +03:00
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:logging/logging.dart';
2021-11-19 17:05:57 +03:00
import '../app/state.dart';
2021-11-19 17:05:57 +03:00
import '../core/state.dart';
import 'models.dart';
final log = Logger('oath.state');
// This remembers the key for all devices for the duration of the process.
final oathLockKeyProvider =
StateNotifierProvider.family<_LockKeyNotifier, String?, List<String>>(
(ref, devicePath) => _LockKeyNotifier(null));
class _LockKeyNotifier extends StateNotifier<String?> {
_LockKeyNotifier(String? state) : super(state);
setKey(String key) {
state = key;
}
2021-12-08 13:20:04 +03:00
unsetKey() {
state = null;
}
}
2021-11-19 17:05:57 +03:00
final oathStateProvider = StateNotifierProvider.autoDispose
.family<OathStateNotifier, OathState?, List<String>>(
(ref, devicePath) => throw UnimplementedError(),
2021-11-19 17:05:57 +03:00
);
abstract class OathStateNotifier extends StateNotifier<OathState?> {
OathStateNotifier() : super(null);
2021-12-08 13:20:04 +03:00
Future<void> reset();
Future<bool> unlock(String password);
Future<bool> setPassword(String? current, String password);
Future<bool> unsetPassword(String current);
2021-11-19 17:05:57 +03:00
}
final credentialListProvider = StateNotifierProvider.autoDispose
.family<OathCredentialListNotifier, List<OathPair>?, List<String>>(
(ref, arg) => throw UnimplementedError(),
2021-11-19 17:05:57 +03:00
);
abstract class OathCredentialListNotifier
extends StateNotifier<List<OathPair>?> {
OathCredentialListNotifier() : super(null);
2021-11-19 17:05:57 +03:00
@override
@protected
set state(List<OathPair>? value) {
super.state = value != null ? List.unmodifiable(value) : null;
}
Future<OathCode> calculate(OathCredential credential);
Future<OathCredential> addAccount(Uri otpauth, {bool requireTouch = false});
Future<OathCredential> renameAccount(
OathCredential credential, String? issuer, String name);
Future<void> deleteAccount(OathCredential credential);
2021-11-19 17:05:57 +03:00
}
2021-12-03 17:15:00 +03:00
final favoritesProvider =
StateNotifierProvider<FavoritesNotifier, List<String>>(
(ref) => FavoritesNotifier(ref.watch(prefProvider)));
2021-11-19 17:05:57 +03:00
2021-12-03 17:15:00 +03:00
class FavoritesNotifier extends StateNotifier<List<String>> {
static const String _key = 'OATH_STATE_FAVORITES';
final SharedPreferences _prefs;
FavoritesNotifier(this._prefs) : super(_prefs.getStringList(_key) ?? []);
2021-12-03 17:15:00 +03:00
toggleFavorite(String credentialId) {
if (state.contains(credentialId)) {
state = state.toList()..remove(credentialId);
} else {
state = [credentialId, ...state];
}
2021-12-03 17:15:00 +03:00
_prefs.setStringList(_key, state);
2021-11-19 17:05:57 +03:00
}
}
final filteredCredentialsProvider = StateNotifierProvider.autoDispose
.family<FilteredCredentialsNotifier, List<OathPair>, List<OathPair>>(
(ref, full) {
2021-12-03 17:15:00 +03:00
return FilteredCredentialsNotifier(full, ref.watch(searchProvider));
2021-11-19 17:05:57 +03:00
});
class FilteredCredentialsNotifier extends StateNotifier<List<OathPair>> {
final String query;
FilteredCredentialsNotifier(
List<OathPair> full,
this.query,
) : super(
full
.where((pair) =>
"${pair.credential.issuer ?? ''}:${pair.credential.name}"
.toLowerCase()
.contains(query.toLowerCase()))
.toList()
..sort((a, b) {
2021-12-03 17:15:00 +03:00
String searchKey(OathCredential c) => (c.issuer ?? '') + c.name;
return searchKey(a.credential).compareTo(searchKey(b.credential));
}),
);
2021-11-19 17:05:57 +03:00
}