알림함 항목 생성 · 알림 이동 · 브리핑 항목 승인·상세 · 푸시 토픽을 가입 팬덤 전체로
This commit is contained in:
@@ -32,8 +32,8 @@ class PushMessaging {
|
||||
StreamSubscription<RemoteMessage>? _opened;
|
||||
StreamSubscription<String>? _tokenRefresh;
|
||||
|
||||
/// 소속 팬덤. 토픽 이름의 일부라 매번 사용자 문서를 읽지 않도록 기억한다.
|
||||
String? _fandomId;
|
||||
/// 가입한 팬덤 전부. 토픽 이름의 일부라 매번 읽지 않도록 기억한다.
|
||||
Set<String>? _fandomIds;
|
||||
|
||||
/// 알림 권한 상태. 화면이 「거부됨」 안내와 재요청 버튼을 그릴 근거다.
|
||||
AuthorizationStatus _status = AuthorizationStatus.notDetermined;
|
||||
@@ -80,16 +80,25 @@ class PushMessaging {
|
||||
}, SetOptions(merge: true));
|
||||
}
|
||||
|
||||
/// 소속 팬덤 ID. 한 번 읽어 두고 다시 읽지 않는다.
|
||||
Future<String> _resolveFandomId() async {
|
||||
final cached = _fandomId;
|
||||
/// 가입한 팬덤 ID 전부 — 대표 팬덤(`users.fandomId`) + 가입 목록(`users/{uid}/memberships`).
|
||||
///
|
||||
/// PRD-06 「관심 아티스트를 등록한 사용자」 · 별첨 1 ③-5 「FCM 푸시 수신」 — 대표 팬덤
|
||||
/// 하나만 구독하면 다른 행성의 브리핑 · 이클립스 예고를 받지 못한다.
|
||||
Future<Set<String>> _resolveFandomIds() async {
|
||||
final cached = _fandomIds;
|
||||
if (cached != null) return cached;
|
||||
final uid = _backend.uid;
|
||||
if (uid == null) return '';
|
||||
if (uid == null) return const {};
|
||||
final user = await _backend.db.doc('users/$uid').get();
|
||||
final id = (user.data() ?? const <String, dynamic>{}).strOr('fandomId');
|
||||
if (id.isNotEmpty) _fandomId = id;
|
||||
return id;
|
||||
final memberships = await _backend.db
|
||||
.collection('users/$uid/memberships')
|
||||
.get();
|
||||
final ids = {
|
||||
(user.data() ?? const <String, dynamic>{}).strOr('fandomId'),
|
||||
for (final d in memberships.docs) d.id,
|
||||
}..remove('');
|
||||
if (ids.isNotEmpty) _fandomIds = ids;
|
||||
return ids;
|
||||
}
|
||||
|
||||
/// 설정대로 토픽을 맞춘다.
|
||||
@@ -102,14 +111,14 @@ class PushMessaging {
|
||||
/// 팬덤 ID 는 사용자 문서에서 스스로 읽는다. 호출자가 넘기게 하면 설정 화면이
|
||||
/// 그 값을 알아야 하고, 화면이 알 이유가 없다.
|
||||
Future<void> syncTopics(Map<PushTopic, bool> prefs) async {
|
||||
final fandomId = await _resolveFandomId();
|
||||
if (fandomId.isEmpty) return;
|
||||
final plan = topicPlan(fandomId, prefs);
|
||||
for (final topic in plan.subscribe) {
|
||||
await _transport.subscribeToTopic(topic);
|
||||
}
|
||||
for (final topic in plan.unsubscribe) {
|
||||
await _transport.unsubscribeFromTopic(topic);
|
||||
for (final fandomId in await _resolveFandomIds()) {
|
||||
final plan = topicPlan(fandomId, prefs);
|
||||
for (final topic in plan.subscribe) {
|
||||
await _transport.subscribeToTopic(topic);
|
||||
}
|
||||
for (final topic in plan.unsubscribe) {
|
||||
await _transport.unsubscribeFromTopic(topic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,8 +151,7 @@ class PushMessaging {
|
||||
/// 토픽 해지를 먼저 하는 이유는 실패 순서다. 토큰 삭제가 실패해도 구독은 끊겨
|
||||
/// 알림이 멈춘다. 반대로 두면 토큰만 지워진 채 토픽 알림이 계속 온다.
|
||||
Future<void> clearOnSignOut() async {
|
||||
final fandomId = await _resolveFandomId();
|
||||
if (fandomId.isNotEmpty) {
|
||||
for (final fandomId in await _resolveFandomIds()) {
|
||||
for (final topic in PushTopic.values) {
|
||||
await _transport.unsubscribeFromTopic(topic.topicFor(fandomId));
|
||||
}
|
||||
@@ -158,7 +166,7 @@ class PushMessaging {
|
||||
}
|
||||
// 다음 로그인은 다른 계정일 수 있다. 팬덤을 들고 있으면 그 계정의 토픽에
|
||||
// 구독해 버린다.
|
||||
_fandomId = null;
|
||||
_fandomIds = null;
|
||||
}
|
||||
|
||||
Future<void> dispose() async {
|
||||
|
||||
Reference in New Issue
Block a user