fluffychat/lib/pangea/common/controllers/pangea_controller.dart
ggurdin 529f12e028
5259 bot settings language settings (#5305)
* feat: add voice to user model

* update bot settings on language / learning settings update

* use room summary to determine member count

* translations
2026-01-21 10:44:21 -05:00

210 lines
6.3 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:get_storage/get_storage.dart';
import 'package:matrix/matrix.dart';
import 'package:provider/provider.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/config/setting_keys.dart';
import 'package:fluffychat/pangea/analytics_misc/client_analytics_extension.dart';
import 'package:fluffychat/pangea/chat_settings/utils/bot_client_extension.dart';
import 'package:fluffychat/pangea/common/utils/p_vguard.dart';
import 'package:fluffychat/pangea/languages/locale_provider.dart';
import 'package:fluffychat/pangea/languages/p_language_store.dart';
import 'package:fluffychat/pangea/subscription/controllers/subscription_controller.dart';
import 'package:fluffychat/pangea/text_to_speech/tts_controller.dart';
import 'package:fluffychat/pangea/user/pangea_push_rules_extension.dart';
import 'package:fluffychat/pangea/user/style_settings_repo.dart';
import 'package:fluffychat/pangea/user/user_controller.dart';
import 'package:fluffychat/widgets/matrix.dart';
import '../utils/firebase_analytics.dart';
class PangeaController {
///pangeaControllers
late UserController userController;
late SubscriptionController subscriptionController;
///store Services
final pLanguageStore = PLanguageStore();
StreamSubscription? _languageSubscription;
StreamSubscription? _settingsSubscription;
StreamSubscription? _joinSpaceSubscription;
///Matrix Variables
final MatrixState matrixState;
PangeaController({required this.matrixState}) {
userController = UserController();
subscriptionController = SubscriptionController(this);
PAuthGaurd.pController = this;
_registerSubscriptions();
}
/// Initializes various controllers and settings.
/// While many of these functions are asynchronous, they are not awaited here,
/// because of order of execution does not matter,
/// and running them at the same times speeds them up.
void initControllers() {
_initAnalytics();
subscriptionController.initialize();
matrixState.client.setPangeaPushRules();
TtsController.setAvailableLanguages();
}
void _onLogin(BuildContext context, String? userID) {
initControllers();
_registerSubscriptions();
userController.reinitialize().then((_) {
final l1 = userController.profile.userSettings.sourceLanguage;
Provider.of<LocaleProvider>(context, listen: false).setLocale(l1);
});
subscriptionController.reinitialize();
StyleSettingsRepo.fontSizeFactor(userID!).then((factor) {
AppConfig.fontSizeFactor = factor;
});
}
void _onLogout(BuildContext context) {
userController.clear();
_languageSubscription?.cancel();
_settingsSubscription?.cancel();
_joinSpaceSubscription?.cancel();
_languageSubscription = null;
_settingsSubscription = null;
_joinSpaceSubscription = null;
GoogleAnalytics.logout();
_clearCache();
Provider.of<LocaleProvider>(context, listen: false).setLocale(null);
}
void handleLoginStateChange(
LoginState state,
String? userID,
BuildContext context,
) {
switch (state) {
case LoginState.loggedOut:
case LoginState.softLoggedOut:
_onLogout(context);
break;
case LoginState.loggedIn:
_onLogin(context, userID);
break;
}
Sentry.configureScope(
(scope) => scope.setUser(
SentryUser(
id: userID,
name: userID,
),
),
);
GoogleAnalytics.analyticsUserUpdate(userID);
}
void _registerSubscriptions() {
_languageSubscription?.cancel();
_languageSubscription =
userController.languageStream.stream.listen(_onLanguageUpdate);
_settingsSubscription?.cancel();
_settingsSubscription = userController.settingsUpdateStream.stream.listen(
(update) => matrixState.client.updateBotOptions(update.userSettings),
);
_joinSpaceSubscription?.cancel();
_joinSpaceSubscription ??= matrixState.client.onSync.stream
.where(matrixState.client.isJoinSpaceSyncUpdate)
.listen((_) => matrixState.client.addAnalyticsRoomsToSpaces());
}
Future<void> _clearCache({List<String> exclude = const []}) async {
final List<Future<void>> futures = [];
for (final key in _storageKeys) {
if (exclude.contains(key)) continue;
futures.add(GetStorage(key).erase());
}
if (AppConfig.showedActivityMenu) {
futures.add(
SharedPreferences.getInstance().then((prefs) async {
AppConfig.showedActivityMenu = false;
prefs.setBool(
SettingKeys.showedActivityMenu,
AppConfig.showedActivityMenu,
);
}),
);
}
await Future.wait(futures);
}
Future<void> _initAnalytics() async {
await GetStorage.init("activity_analytics_storage");
matrixState.client.updateAnalyticsRoomJoinRules();
matrixState.client.addAnalyticsRoomsToSpaces();
}
Future<void> resetAnalytics() async {
await _initAnalytics();
}
Future<void> _onLanguageUpdate(LanguageUpdate update) async {
final exclude = [
'course_location_media_storage',
'course_location_storage',
'course_media_storage',
];
// only clear course data if the base language has changed
if (update.prevBaseLang == update.baseLang) {
exclude.addAll([
'course_storage',
'course_topic_storage',
'course_activity_storage',
]);
}
_clearCache(exclude: exclude);
matrixState.client.updateBotOptions(userController.profile.userSettings);
}
static final List<String> _storageKeys = [
'mode_list_storage',
'activity_plan_storage',
'bookmarked_activities',
'objective_list_storage',
'topic_list_storage',
'activity_plan_search_storage',
"version_storage",
'lemma_storage',
'svg_cache',
'morphs_storage',
'morph_meaning_storage',
'practice_record_cache',
'practice_selection_cache',
'subscription_storage',
'vocab_storage',
'onboarding_storage',
'analytics_request_storage',
'activity_analytics_storage',
'course_storage',
'course_topic_storage',
'course_media_storage',
'course_location_storage',
'course_activity_storage',
'course_location_media_storage',
'language_mismatch',
];
}