feat(flutter): persist poke notification preferences

This commit is contained in:
Edison Jwa
2026-06-08 22:55:12 +09:00
parent 4f1b85cf76
commit 409cd11c21
2 changed files with 116 additions and 0 deletions
@@ -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);
});
}