fix: add base language dropdown to language selection page on identic… (#4384)

* fix: add base language dropdown to language selection page on identical target and system language

* Update lib/pangea/login/utils/lang_code_repo.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
ggurdin 2025-10-14 16:24:44 -04:00 committed by GitHub
parent 7579b657f3
commit cd03c2ef2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 101 additions and 35 deletions

View file

@ -17,10 +17,8 @@ class PLanguageDropdown extends StatefulWidget {
final bool isL2List;
final String? decorationText;
final String? error;
final String? Function(LanguageModel?)? validator;
final Color? backgroundColor;
final bool hasError;
final bool enabled;
const PLanguageDropdown({
super.key,
@ -30,10 +28,8 @@ class PLanguageDropdown extends StatefulWidget {
this.decorationText,
this.isL2List = false,
this.error,
this.validator,
this.backgroundColor,
this.hasError = false,
this.enabled = true,
});
@override
@ -87,14 +83,12 @@ class PLanguageDropdownState extends State<PLanguageDropdown> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DropdownButtonFormField2<LanguageModel>(
enableFeedback: widget.enabled,
customButton: widget.initialLanguage != null &&
sortedLanguages.contains(widget.initialLanguage)
? LanguageDropDownEntry(
languageModel: widget.initialLanguage!,
isL2List: widget.isL2List,
isDropdown: true,
enabled: widget.enabled,
)
: null,
menuItemStyleData: const MenuItemStyleData(
@ -144,15 +138,13 @@ class PLanguageDropdownState extends State<PLanguageDropdown> {
child: LanguageDropDownEntry(
languageModel: languageModel,
isL2List: widget.isL2List,
enabled: widget.enabled,
),
),
),
),
],
onChanged: widget.enabled ? (value) => widget.onChange(value!) : null,
onChanged: (value) => widget.onChange(value!),
value: widget.initialLanguage,
validator: (value) => widget.validator?.call(value),
dropdownSearchData: DropdownSearchData(
searchController: _searchController,
searchInnerWidgetHeight: 50,

View file

@ -49,10 +49,14 @@ class CreatePangeaAccountPageState extends State<CreatePangeaAccountPage> {
String? _spaceId;
String? _courseLangCode;
Future<String?> get _cachedLangCode => LangCodeRepo.get();
Future<LanguageSettings?> get _cachedLangCode => LangCodeRepo.get();
Future<String?> get _langCode async =>
_courseLangCode ?? (await _cachedLangCode);
Future<String?> get _targetLangCode async =>
_courseLangCode ?? (await _cachedLangCode)?.targetLangCode;
Future<String?> get _baseLangCode async =>
(await _cachedLangCode)?.baseLangCode ??
MatrixState.pangeaController.languageController.systemLanguage?.langCode;
String? get _cachedSpaceCode =>
MatrixState.pangeaController.spaceCodeController.cachedSpaceCode;
@ -137,11 +141,15 @@ class CreatePangeaAccountPageState extends State<CreatePangeaAccountPage> {
}
}
Future<void> _updateTargetLanguage() async {
final langCode = await _langCode;
Future<void> _updateLanguageSettings() async {
final targetLangCode = await _targetLangCode;
final baseLangCode = await _baseLangCode;
await MatrixState.pangeaController.userController.updateProfile(
(profile) {
profile.userSettings.targetLanguage = langCode;
profile.userSettings.targetLanguage = targetLangCode;
if (baseLangCode != null) {
profile.userSettings.sourceLanguage = baseLangCode;
}
return profile;
},
waitForDataInSync: true,
@ -151,33 +159,30 @@ class CreatePangeaAccountPageState extends State<CreatePangeaAccountPage> {
Future<void> _createUserInPangea() async {
final l2Set = await MatrixState.pangeaController.userController.isUserL2Set;
if (l2Set) {
await _updateTargetLanguage();
await _updateLanguageSettings();
_onProfileCreated();
return;
}
try {
final langCode = await _langCode;
final targetLangCode = await _targetLangCode;
final baseLangCode = await _baseLangCode;
final updateFuture = [
_setAvatar(),
MatrixState.pangeaController.userController.updateProfile(
(profile) {
final systemLang = MatrixState
.pangeaController.languageController.systemLanguage?.langCode;
if (systemLang != null) {
profile.userSettings.sourceLanguage = systemLang;
profile.userSettings.targetLanguage = targetLangCode;
if (baseLangCode != null) {
profile.userSettings.sourceLanguage = baseLangCode;
}
profile.userSettings.targetLanguage = langCode;
profile.userSettings.createdAt = DateTime.now();
return profile;
},
waitForDataInSync: true,
),
if (langCode != null)
if (targetLangCode != null)
MatrixState.pangeaController.userController.updateAnalyticsProfile(
targetLanguage: PLanguageStore.byLangCode(langCode),
targetLanguage: PLanguageStore.byLangCode(targetLangCode),
baseLanguage:
MatrixState.pangeaController.languageController.systemLanguage,
level: 1,

View file

@ -2,11 +2,15 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/pangea/learning_settings/models/language_model.dart';
import 'package:fluffychat/pangea/learning_settings/widgets/p_language_dropdown.dart';
import 'package:fluffychat/pangea/login/utils/lang_code_repo.dart';
import 'package:fluffychat/widgets/matrix.dart';
class IdenticalLanguageException implements Exception {}
class LanguageSelectionPage extends StatefulWidget {
const LanguageSelectionPage({super.key});
@ -15,21 +19,41 @@ class LanguageSelectionPage extends StatefulWidget {
}
class LanguageSelectionPageState extends State<LanguageSelectionPage> {
Object? _error;
LanguageModel? _selectedLanguage;
LanguageModel? _baseLanguage;
@override
void initState() {
super.initState();
_baseLanguage =
MatrixState.pangeaController.languageController.systemLanguage;
}
void _setSelectedLanguage(LanguageModel? l) {
setState(() => _selectedLanguage = l);
}
Future<void> _submit() async {
if (_selectedLanguage == null) return;
void _setBaseLanguage(LanguageModel? l) {
setState(() => _baseLanguage = l);
}
await LangCodeRepo.set(_selectedLanguage!.langCode);
Future<void> _submit() async {
setState(() => _error = null);
if (_selectedLanguage == null) return;
if (_selectedLanguage?.langCodeShort == _baseLanguage?.langCodeShort) {
setState(() => _error = IdenticalLanguageException());
return;
}
await LangCodeRepo.set(
LanguageSettings(
targetLangCode: _selectedLanguage!.langCode,
baseLangCode: _baseLanguage?.langCode,
),
);
context.go(
GoRouterState.of(context).fullPath?.contains('home') == true
? '/home/language/signup'
@ -56,7 +80,6 @@ class LanguageSelectionPageState extends State<LanguageSelectionPage> {
child: Column(
spacing: 24.0,
children: [
const SizedBox(height: 50.0),
Expanded(
child: Stack(
children: [
@ -119,6 +142,22 @@ class LanguageSelectionPageState extends State<LanguageSelectionPage> {
],
),
),
AnimatedSize(
duration: FluffyThemes.animationDuration,
child: _selectedLanguage != null &&
_selectedLanguage?.langCodeShort ==
_baseLanguage?.langCodeShort
? PLanguageDropdown(
languages: languages,
onChange: _setBaseLanguage,
initialLanguage: _baseLanguage,
decorationText: L10n.of(context).myBaseLanguage,
error: _error is IdenticalLanguageException
? L10n.of(context).noIdenticalLanguages
: null,
)
: const SizedBox(),
),
Text(
L10n.of(context).chooseLanguage,
style: theme.textTheme.titleMedium?.copyWith(

View file

@ -1,24 +1,54 @@
import 'package:get_storage/get_storage.dart';
class LanguageSettings {
final String targetLangCode;
final String? baseLangCode;
LanguageSettings({
required this.targetLangCode,
this.baseLangCode,
});
Map<String, dynamic> toJson() => {
'targetLangCode': targetLangCode,
'baseLangCode': baseLangCode,
};
factory LanguageSettings.fromJson(Map<String, dynamic> json) =>
LanguageSettings(
targetLangCode: json['targetLangCode'],
baseLangCode: json['baseLangCode'],
);
}
class LangCodeRepo {
static const String _storageKey = 'lang_settings';
static final GetStorage _storage = GetStorage('lang_code_storage');
static Future<void> _init() async {
await GetStorage.init('lang_code_storage');
}
static Future<String?> get() async {
static Future<LanguageSettings?> get() async {
await _init();
return _storage.read('lang_code');
final entry = _storage.read(_storageKey);
if (entry == null) return null;
try {
return LanguageSettings.fromJson(entry);
} catch (e) {
await remove();
return null;
}
}
static Future<void> set(String langcode) async {
static Future<void> set(LanguageSettings langcode) async {
await _init();
await _storage.write('lang_code', langcode);
await _storage.write(_storageKey, langcode.toJson());
}
static Future<void> remove() async {
await _init();
await _storage.remove('lang_code');
await _storage.remove(_storageKey);
}
}