@@ -12,6 +12,8 @@ public class SettingsViewModel : BaseViewModel, ISettingsViewModel
1212 public SettingsViewModel ( )
1313 {
1414 this . Title = AppSnippets . Settings ;
15+ // Initialize birthDate with a reasonable default to avoid binding issues
16+ this . _birthDate = DateTime . Today . AddYears ( - 25 ) ;
1517 ResetCommand = new Command ( ( ) =>
1618 {
1719 Preferences . Remove ( PreferencesKeys . ApiServerAddressOverride ) ;
@@ -23,6 +25,11 @@ public SettingsViewModel()
2325 Preferences . Remove ( PreferencesKeys . MuscleMassAsPercentage ) ;
2426 Preferences . Remove ( PreferencesKeys . DisplayWeightInLbs ) ;
2527 Preferences . Remove ( PreferencesKeys . UseChinaServer ) ;
28+ Preferences . Remove ( PreferencesKeys . UserAge ) ;
29+ Preferences . Remove ( PreferencesKeys . UserBirthDate ) ;
30+ Preferences . Remove ( PreferencesKeys . UseBirthDateMode ) ;
31+ this . UseBirthDateMode = false ;
32+ this . ManualAge = "25" ;
2633 }
2734 ) ;
2835 GetBLEKeyCommand = new Command ( async ( ) => await Launcher . OpenAsync ( "https://lswiderski.github.io/mi-scale-exporter/#steps-to-connect-xiaomi-body-composition-scale-s400" ) ) ;
@@ -36,31 +43,55 @@ public SettingsViewModel()
3643
3744 public async Task LoadPreferencesAsync ( )
3845 {
39- this . _apiAddress = Preferences . Get ( PreferencesKeys . ApiServerAddressOverride , string . Empty ) ;
40- this . _oneClickScanAndUpload = Preferences . Get ( PreferencesKeys . OneClickScanAndUpload , false ) ;
41- this . _useExternalAPI = Preferences . Get ( PreferencesKeys . UseExternalAPI , false ) ;
42- this . _showDebugInfo = Preferences . Get ( PreferencesKeys . ShowDebugInfo , false ) ;
43- this . _hideAds = Preferences . Get ( PreferencesKeys . HideAds , false ) ;
44- this . _muscleMassAsPercentage = Preferences . Get ( PreferencesKeys . MuscleMassAsPercentage , false ) ;
45- this . _displayWeightInLbs = Preferences . Get ( PreferencesKeys . DisplayWeightInLbs , false ) ;
46- this . _useChinaServer = Preferences . Get ( PreferencesKeys . UseChinaServer , false ) ;
47-
48- this . _age = Preferences . Get ( PreferencesKeys . UserAge , 25 ) ;
49- this . _height = Preferences . Get ( PreferencesKeys . UserHeight , 170 ) ;
50- this . _sex = ( Sex ) Preferences . Get ( PreferencesKeys . UserSex , ( byte ) Sex . Male ) ;
51- this . _address = Preferences . Get ( PreferencesKeys . MiScaleBluetoothAddress , string . Empty ) ;
52- this . _scaleType = ( ScaleType ) Preferences . Get ( PreferencesKeys . ScaleType , ( byte ) ScaleType . MiBodyCompositionScale ) ;
53- this . _email = Preferences . Get ( PreferencesKeys . GarminUserEmail , string . Empty ) ;
54- this . _password = await SecureStorage . GetAsync ( PreferencesKeys . GarminUserPassword ) ;
55- this . _bindkey = Preferences . Get ( PreferencesKeys . S400Bindkey , string . Empty ) ;
56- NotifyAllPropertiesChanged ( ) ;
46+ _isLoadingPreferences = true ;
47+ try
48+ {
49+ this . _apiAddress = Preferences . Get ( PreferencesKeys . ApiServerAddressOverride , string . Empty ) ;
50+ this . _oneClickScanAndUpload = Preferences . Get ( PreferencesKeys . OneClickScanAndUpload , false ) ;
51+ this . _useExternalAPI = Preferences . Get ( PreferencesKeys . UseExternalAPI , false ) ;
52+ this . _showDebugInfo = Preferences . Get ( PreferencesKeys . ShowDebugInfo , false ) ;
53+ this . _hideAds = Preferences . Get ( PreferencesKeys . HideAds , false ) ;
54+ this . _muscleMassAsPercentage = Preferences . Get ( PreferencesKeys . MuscleMassAsPercentage , false ) ;
55+ this . _displayWeightInLbs = Preferences . Get ( PreferencesKeys . DisplayWeightInLbs , false ) ;
56+ this . _useChinaServer = Preferences . Get ( PreferencesKeys . UseChinaServer , false ) ;
57+
58+ // Load age or birthday mode
59+ this . _useBirthDateMode = Preferences . Get ( PreferencesKeys . UseBirthDateMode , false ) ;
60+
61+ if ( _useBirthDateMode )
62+ {
63+ // Load birthday
64+ var birthDateTicks = Preferences . Get ( PreferencesKeys . UserBirthDate , 0L ) ;
65+ this . _birthDate = birthDateTicks > 0 ? new DateTime ( birthDateTicks ) : DateTime . Today . AddYears ( - 25 ) ;
66+ this . _manualAge = 0 ; // Not used in birthday mode
67+ }
68+ else
69+ {
70+ // Load manual age
71+ this . _manualAge = Preferences . Get ( PreferencesKeys . UserAge , 25 ) ;
72+ this . _birthDate = DateTime . Today . AddYears ( - _manualAge ) ; // For reference only
73+ }
74+
75+ this . _height = Preferences . Get ( PreferencesKeys . UserHeight , 170 ) ;
76+ this . _sex = ( Sex ) Preferences . Get ( PreferencesKeys . UserSex , ( byte ) Sex . Male ) ;
77+ this . _address = Preferences . Get ( PreferencesKeys . MiScaleBluetoothAddress , string . Empty ) ;
78+ this . _scaleType = ( ScaleType ) Preferences . Get ( PreferencesKeys . ScaleType , ( byte ) ScaleType . MiBodyCompositionScale ) ;
79+ this . _email = Preferences . Get ( PreferencesKeys . GarminUserEmail , string . Empty ) ;
80+ this . _password = await SecureStorage . GetAsync ( PreferencesKeys . GarminUserPassword ) ;
81+ this . _bindkey = Preferences . Get ( PreferencesKeys . S400Bindkey , string . Empty ) ;
82+ NotifyAllPropertiesChanged ( ) ;
83+ }
84+ finally
85+ {
86+ _isLoadingPreferences = false ;
87+ }
5788 }
5889
5990 private bool ValidateProfile ( )
6091 {
6192 return ! String . IsNullOrWhiteSpace ( _address )
6293 && _height > 0 && _height < 220
63- && _age > 0 && _age < 99 ;
94+ && Age > 0 && Age < 99 ;
6495 }
6596
6697 private string _apiAddress ;
@@ -228,17 +259,78 @@ public string Bindkey
228259
229260 private int _age ;
230261
231- public string Age
262+ public int Age
263+ {
264+ get
265+ {
266+ if ( _useBirthDateMode )
267+ {
268+ // Calculate age from birthday
269+ var today = DateTime . Today ;
270+ var age = today . Year - _birthDate . Year ;
271+ if ( _birthDate . Date > today . AddYears ( - age ) )
272+ {
273+ age -- ;
274+ }
275+ return age ;
276+ }
277+ else
278+ {
279+ // Return manually entered age
280+ return _manualAge ;
281+ }
282+ }
283+ }
284+
285+ private int _manualAge ;
286+
287+ public string ManualAge
232288 {
233- get => _age . ToString ( ) ;
289+ get => _manualAge . ToString ( ) ;
234290 set
235291 {
236292 if ( value is null ) return ;
237293 if ( int . TryParse ( value , out var result ) )
238294 {
239- SetProperty ( ref _age , result ) ;
295+ SetProperty ( ref _manualAge , result ) ;
240296 if ( result == 0 ) return ;
241297 Preferences . Set ( PreferencesKeys . UserAge , result ) ;
298+ OnPropertyChanged ( nameof ( Age ) ) ;
299+ }
300+ }
301+ }
302+
303+ private bool _useBirthDateMode ;
304+
305+ public bool UseBirthDateMode
306+ {
307+ get => _useBirthDateMode ;
308+ set
309+ {
310+ if ( SetProperty ( ref _useBirthDateMode , value ) )
311+ {
312+ Preferences . Set ( PreferencesKeys . UseBirthDateMode , value ) ;
313+ OnPropertyChanged ( nameof ( Age ) ) ;
314+ }
315+ }
316+ }
317+
318+ private DateTime _birthDate ;
319+ private bool _isLoadingPreferences = false ;
320+
321+ public DateTime BirthDate
322+ {
323+ get => _birthDate ;
324+ set
325+ {
326+ if ( SetProperty ( ref _birthDate , value ) )
327+ {
328+ // Only save to preferences if we're not in the middle of loading
329+ if ( ! _isLoadingPreferences )
330+ {
331+ Preferences . Set ( PreferencesKeys . UserBirthDate , value . Ticks ) ;
332+ OnPropertyChanged ( nameof ( Age ) ) ;
333+ }
242334 }
243335 }
244336 }
0 commit comments