57 lines
2.3 KiB
Dart
57 lines
2.3 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
/// 원격 기능 플래그 — Firestore `config/features` 문서 한 장.
|
|
///
|
|
/// 별첨 B v1.4 (STATION) — *1차에서는 사용자 탭과 Coming Soon 을 모두 비노출하고
|
|
/// Route/데이터 구조만 유지해 향후 **앱 재배포 없이** 활성화합니다.*
|
|
///
|
|
/// 「재배포 없이」가 이 클래스가 존재하는 이유 전부다. 컴파일 상수나
|
|
/// `--dart-define` 은 값을 바꾸려면 새 빌드를 올려야 해 회신 문구를 만족하지 못한다.
|
|
/// 반대로 `firebase_remote_config` 는 신규 의존성이라 pubspec 머리말대로 최소 지원
|
|
/// OS 를 다시 계산해야 하는데, `firestore.rules` 의 `config/{id}` 가 이미
|
|
/// `allow read: if true` 로 열려 있고 `cloud_firestore` 는 이미 들어와 있다.
|
|
/// 그래서 이미 있는 것으로 끝낸다.
|
|
///
|
|
/// **기본값은 전부 꺼짐이다.** 문서가 없거나, 목 모드거나, 읽기가 실패해도 STATION
|
|
/// 은 나타나지 않는다 — 「원격 값을 못 읽었다」가 「켜졌다」가 되면 안 된다.
|
|
class FeatureFlags extends ChangeNotifier {
|
|
FeatureFlags({Stream<Map<String, Object?>>? source}) {
|
|
if (source != null) _subscription = source.listen(_apply, onError: _ignore);
|
|
}
|
|
|
|
/// Firestore 문서 ID. 서버 설계서에 넘기는 계약 이름이다.
|
|
static const String documentPath = 'config/features';
|
|
|
|
/// STATION 탭 노출 스위치. 문서의 `stationEnabled`(bool) 하나를 읽는다.
|
|
static const String stationKey = 'stationEnabled';
|
|
|
|
StreamSubscription<Map<String, Object?>>? _subscription;
|
|
|
|
bool _stationTab = false;
|
|
|
|
/// 하단 탭에 STATION 을 그릴 것인가. 기본 false.
|
|
bool get stationTab => _stationTab;
|
|
|
|
void _apply(Map<String, Object?> data) {
|
|
// 타입까지 확인한다. 누가 문자열 "true" 를 넣어도 켜지지 않는다.
|
|
final next = data[stationKey] == true;
|
|
if (next == _stationTab) return;
|
|
_stationTab = next;
|
|
notifyListeners();
|
|
}
|
|
|
|
/// 원격 읽기 실패는 꺼짐 상태를 유지하는 것으로 끝낸다. 화면에 띄울 것이 없다.
|
|
void _ignore(Object error) {
|
|
debugPrint('[FeatureFlags] read failed: ${error.runtimeType}');
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
unawaited(_subscription?.cancel());
|
|
_subscription = null;
|
|
super.dispose();
|
|
}
|
|
}
|