guru_sdk/guru_app/lib/account/account_data_store.dart

125 lines
4.1 KiB
Dart
Raw Normal View History

import 'dart:convert';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:guru_app/account/model/account_profile.dart';
import 'package:guru_app/account/model/user.dart';
import 'package:guru_app/analytics/guru_analytics.dart';
import 'package:guru_app/api/guru_api.dart';
import 'package:guru_app/guru_app.dart';
import 'package:guru_app/property/app_property.dart';
import 'package:guru_utils/device/device_info.dart';
import 'package:guru_utils/extensions/extensions.dart';
import 'package:http/http.dart' as http;
/// Created by Haoyi on 6/3/21
///
enum AccountDataStatus { idle, initializing, initialized, waiting, error }
class AccountDataStore {
static final AccountDataStore instance = AccountDataStore._();
final BehaviorSubject<DeviceInfo?> _deviceInfoSubject = BehaviorSubject.seeded(null);
final BehaviorSubject<SaasUser?> _saasUserSubject = BehaviorSubject.seeded(null);
final BehaviorSubject<User?> _firebaseUser = BehaviorSubject.seeded(null);
final BehaviorSubject<AccountProfile?> _accountProfile = BehaviorSubject.seeded(null);
final BehaviorSubject<AccountDataStatus> _accountDataStatus =
BehaviorSubject<AccountDataStatus>.seeded(AccountDataStatus.idle);
int initRetryCount = 0;
Stream<AccountProfile?> get observableAccountProfile => _accountProfile.stream;
// final EnvConfig envConfig;
AccountDataStore._();
String? get saasToken => _saasUserSubject.value?.token;
String? get uid => _saasUserSubject.value?.uid;
AccountProfile? get accountProfile => _accountProfile.value;
String? get nickname => _accountProfile.value?.nickname;
String? get countryCode => _accountProfile.value?.countryCode;
SaasUser? get user => _saasUserSubject.value;
String? get avatar => _accountProfile.value?.avatar;
DeviceInfo? get currentDevice => _deviceInfoSubject.value;
AccountDataStatus get accountDataStatus => _accountDataStatus.value;
bool get initialized => _accountDataStatus.value == AccountDataStatus.initialized;
Stream<bool> get observableInitialized =>
_accountDataStatus.stream.map((status) => status == AccountDataStatus.initialized);
Stream<SaasUser?> get observableSaasUser => _saasUserSubject.stream;
void dispose() {
_deviceInfoSubject.close();
_saasUserSubject.close();
_firebaseUser.close();
_accountProfile.close();
}
Future<SaasUser?> signInAnonymousInLocked() async {
// 这里需要使用原始的http post请求。否则这里将会死锁DIO所有请求
final secret = await AppProperty.getInstance().getAnonymousSecretKey();
final headers = {
"X-APP-ID": GuruApp.instance.details.saasAppId,
"content-type": "application/json"
};
try {
final uri = Uri.parse("${GuruApi.saasApiHost}/auth/api/v1/tokens/provider/secret");
final response = await http
.post(uri,
headers: headers,
body: jsonEncode(AnonymousLoginReqBody(secret: secret)),
encoding: utf8)
.timeout(const Duration(seconds: 30));
final data = const Utf8Decoder().convert(response.bodyBytes);
if (data.isNotEmpty) {
final result = json.decode(data);
return SaasUser.fromJson(result["data"]);
}
} catch (error, stacktrace) {
Log.v("signInAnonymousInLocked error:$error", tag: "Account");
}
return null;
}
Future refreshAuth() async {
final saasUser = await signInAnonymousInLocked();
if (saasUser != null) {
updateSaasUser(saasUser);
}
}
void updateDeviceInfo(DeviceInfo deviceInfo) {
_deviceInfoSubject.addEx(deviceInfo);
}
void updateSaasUser(SaasUser saasUser) {
_saasUserSubject.addEx(saasUser);
if (saasUser.createAtTimestamp > 0) {
GuruAnalytics.instance
.setUserProperty("user_created_timestamp", saasUser.createAtTimestamp.toString());
}
}
void updateFirebaseUser(User user) {
_firebaseUser.addEx(user);
}
void updateAccountProfile(AccountProfile profile) {
_accountProfile.addEx(profile);
}
bool transitionTo(AccountDataStatus status, {AccountDataStatus? expectStatus}) {
return _accountDataStatus.addIfChanged(status);
}
}