app_environment_config.dart 3.66 KB
import 'package:doublefeel_flutter/core/network/dio_client.dart';
import 'package:doublefeel_flutter/core/platform/pigeon_api_facade.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';

import '../constants/app_const.dart';
import '../constants/storage_const.dart';
import '../../data/local/local_storage.dart';
import 'app_environment.dart';

/// Resolves API base URL and third-party keys by environment.
class AppEnvironmentConfig {
  AppEnvironmentConfig(this._storage);

  final LocalStorage _storage;
  final AppPlatformHostApi _platformHostApi = AppPlatformHostApi();

  final Rx<AppEnvironment> environment = AppEnvironment.release.obs;

  Future<AppEnvironmentConfig> init() async {
    environment.value = await _storage.readEnvironment();
    _isNativeDebug = await _platformHostApi.isDebugEnvoriment();
    final stored = await _storage.readRegion();
    if (stored == null) {
      final detected = await _detectRegion();
      await setRegion(detected);
    } else {
      region.value = stored;
    }
    if (stored == AppRegion.global) {
      await _storage.setTermsAgreed(true);
    }
    return this;
  }

  Future<AppRegion> _detectRegion() async {
    try {
      return await _platformHostApi.isChinaRegion()
          ? AppRegion.china
          : AppRegion.global;
    } catch (_) {
      return _detectRegionFromLocale();
    }
  }

  AppRegion _detectRegionFromLocale() {
    final country = WidgetsBinding
        .instance.platformDispatcher.locale.countryCode
        ?.toUpperCase();
    return switch (country) {
      'CN' => AppRegion.china,
      _ => AppRegion.global,
    };
  }

  Future<void> setEnvironment(AppEnvironment value) async {
    environment.value = value;
    await _storage.writeEnvironment(value);
  }

  bool _isNativeDebug = false;

  bool get isDebug => kDebugMode || _isNativeDebug;

  final Rx<AppRegion> region = AppRegion.global.obs;

  Future<void> setRegion(AppRegion value) async {
    region.value = value;
    try {
      await _storage.writeRegion(value);
      if (Get.isRegistered<DioClient>()) {
        Get.find<DioClient>().refreshBaseUrl();
      }
    } catch (e) {
      debugPrint('setRegion failed: $e');
    }
  }

  get hideChooseRegion => _storage.hideChooseRegion;

  Future<void> updateHideChooseRegion(bool value) async {
    await _storage.writeHideChooseRegion(value);
  }

  String get serverBaseUrl {
    final regionUrl = switch (region.value) {
      AppRegion.china => AppConst.serverBaseUrl,
      AppRegion.global => AppConst.serverBaseUrlGlobal,
    };
    return resolveServerUrl(regionUrl);
  }

  String resolveServerUrl(String url) {
    return resolveServerUrlFor(environment.value, url);
  }

  String resolveServerUrlFor(AppEnvironment targetEnvironment, String url) {
    try {
      final uri = Uri.parse(url);
      final host = uri.host;
      final resolvedHost = switch (targetEnvironment) {
        AppEnvironment.xlab => '${AppConst.prefixXlabServerHost}-$host',
        AppEnvironment.dev => '${AppConst.prefixDevServerHost}-$host',
        AppEnvironment.release => host,
      };
      if (resolvedHost == host) {
        return url;
      }
      return uri.replace(host: resolvedHost).toString();
    } catch (_) {
      return url;
    }
  }

  String get rongCloudAppKey => environment.value == AppEnvironment.dev
      ? AppConst.appKeyRongCloudDev
      : AppConst.appKeyRongCloudProduct;

  String get thinkingDataAppId => environment.value == AppEnvironment.dev
      ? AppConst.appIdThinkingDataDebug
      : AppConst.appIdThinkingDataRelease;

  static const environmentPrefsName = StorageConst.appEnvironmentPrefsName;
}

enum AppRegion { china, global }