feat(flutter): persist poke notification preferences
This commit is contained in:
@@ -0,0 +1,58 @@
|
|||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
class PokePreferencesService {
|
||||||
|
static const _enabledKey = 'pokes.enabled';
|
||||||
|
static const _mutedSendersKey = 'pokes.muted_senders';
|
||||||
|
|
||||||
|
final ValueNotifier<bool> _pokesEnabled = ValueNotifier<bool>(true);
|
||||||
|
final ValueNotifier<Set<BigInt>> _mutedSenders = ValueNotifier<Set<BigInt>>(
|
||||||
|
const <BigInt>{},
|
||||||
|
);
|
||||||
|
|
||||||
|
ValueListenable<bool> get pokesEnabled => _pokesEnabled;
|
||||||
|
ValueListenable<Set<BigInt>> get mutedSenders => _mutedSenders;
|
||||||
|
|
||||||
|
Future<void> load() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
_pokesEnabled.value = prefs.getBool(_enabledKey) ?? true;
|
||||||
|
_mutedSenders.value = (prefs.getStringList(_mutedSendersKey) ?? const [])
|
||||||
|
.map(BigInt.parse)
|
||||||
|
.toSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setPokesEnabled(bool enabled) async {
|
||||||
|
_pokesEnabled.value = enabled;
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.setBool(_enabledKey, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> muteSender(BigInt senderId) async {
|
||||||
|
if (_mutedSenders.value.contains(senderId)) return;
|
||||||
|
_mutedSenders.value = {..._mutedSenders.value, senderId};
|
||||||
|
await _saveMutedSenders();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> unmuteSender(BigInt senderId) async {
|
||||||
|
if (!_mutedSenders.value.contains(senderId)) return;
|
||||||
|
_mutedSenders.value = _mutedSenders.value
|
||||||
|
.where((mutedSender) => mutedSender != senderId)
|
||||||
|
.toSet();
|
||||||
|
await _saveMutedSenders();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isMuted(BigInt senderId) => _mutedSenders.value.contains(senderId);
|
||||||
|
|
||||||
|
Future<void> _saveMutedSenders() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.setStringList(
|
||||||
|
_mutedSendersKey,
|
||||||
|
_mutedSenders.value.map((senderId) => senderId.toString()).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
_pokesEnabled.dispose();
|
||||||
|
_mutedSenders.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import 'package:chanora_flutter/services/poke_preferences_service.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
late PokePreferencesService service;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
SharedPreferences.setMockInitialValues({});
|
||||||
|
service = PokePreferencesService();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('loads defaults when preferences are unset', () async {
|
||||||
|
await service.load();
|
||||||
|
|
||||||
|
expect(service.pokesEnabled.value, isTrue);
|
||||||
|
expect(service.mutedSenders.value, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('persists global enabled state', () async {
|
||||||
|
await service.load();
|
||||||
|
await service.setPokesEnabled(false);
|
||||||
|
|
||||||
|
final reloaded = PokePreferencesService();
|
||||||
|
await reloaded.load();
|
||||||
|
|
||||||
|
expect(reloaded.pokesEnabled.value, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('persists muted senders and removes them on unmute', () async {
|
||||||
|
await service.load();
|
||||||
|
final alice = BigInt.from(42);
|
||||||
|
final bob = BigInt.from(7);
|
||||||
|
|
||||||
|
await service.muteSender(alice);
|
||||||
|
await service.muteSender(bob);
|
||||||
|
await service.unmuteSender(alice);
|
||||||
|
|
||||||
|
final reloaded = PokePreferencesService();
|
||||||
|
await reloaded.load();
|
||||||
|
|
||||||
|
expect(reloaded.mutedSenders.value, {bob});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('isMuted reflects in-memory changes synchronously', () async {
|
||||||
|
await service.load();
|
||||||
|
final sender = BigInt.from(99);
|
||||||
|
|
||||||
|
expect(service.isMuted(sender), isFalse);
|
||||||
|
|
||||||
|
await service.muteSender(sender);
|
||||||
|
expect(service.isMuted(sender), isTrue);
|
||||||
|
|
||||||
|
await service.unmuteSender(sender);
|
||||||
|
expect(service.isMuted(sender), isFalse);
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user