22using System . Collections . Generic ;
33using System . IO ;
44using System . Text . Json ;
5+ using System . Text . Json . Serialization ;
56
67namespace Coder . Desktop . App . Services ;
78
@@ -28,10 +29,10 @@ public interface ISettingsManager
2829public sealed class SettingsManager : ISettingsManager
2930{
3031 private readonly string _settingsFilePath ;
32+ private Settings _settings ;
3133 private readonly string _fileName = "app-settings.json" ;
3234 private readonly string _appName = "CoderDesktop" ;
3335 private readonly object _lock = new ( ) ;
34- private Dictionary < string , JsonElement > _cache ;
3536
3637 public const string ConnectOnLaunchKey = "ConnectOnLaunch" ;
3738 public const string StartOnLoginKey = "StartOnLogin" ;
@@ -87,9 +88,12 @@ public SettingsManager(string? settingsFilePath = null)
8788 // Create the settings file if it doesn't exist
8889 string emptyJson = JsonSerializer . Serialize ( new { } ) ;
8990 File . WriteAllText ( _settingsFilePath , emptyJson ) ;
91+ _settings = new ( ) ;
92+ }
93+ else
94+ {
95+ _settings = Load ( ) ;
9096 }
91-
92- _cache = Load ( ) ;
9397 }
9498
9599 private void Save ( string name , bool value )
@@ -105,12 +109,12 @@ private void Save(string name, bool value)
105109 FileShare . None ) ;
106110
107111 // Ensure cache is loaded before saving
108- var currentCache = JsonSerializer . Deserialize < Dictionary < string , JsonElement > > ( fs ) ?? [ ] ;
109- _cache = currentCache ;
110- _cache [ name ] = JsonSerializer . SerializeToElement ( value ) ;
112+ var freshCache = JsonSerializer . Deserialize < Settings > ( fs ) ?? new ( ) ;
113+ _settings = freshCache ;
114+ _settings . Options [ name ] = JsonSerializer . SerializeToElement ( value ) ;
111115 fs . Position = 0 ; // Reset stream position to the beginning before writing
112116
113- JsonSerializer . Serialize ( fs , _cache , new JsonSerializerOptions { WriteIndented = true } ) ;
117+ JsonSerializer . Serialize ( fs , _settings , new JsonSerializerOptions { WriteIndented = true } ) ;
114118
115119 // This ensures the file is truncated to the new length
116120 // if the new content is shorter than the old content
@@ -127,7 +131,7 @@ private bool Read(string name, bool defaultValue)
127131 {
128132 lock ( _lock )
129133 {
130- if ( _cache . TryGetValue ( name , out var element ) )
134+ if ( _settings . Options . TryGetValue ( name , out var element ) )
131135 {
132136 try
133137 {
@@ -143,16 +147,38 @@ private bool Read(string name, bool defaultValue)
143147 }
144148 }
145149
146- private Dictionary < string , JsonElement > Load ( )
150+ private Settings Load ( )
147151 {
148152 try
149153 {
150154 using var fs = File . OpenRead ( _settingsFilePath ) ;
151- return JsonSerializer . Deserialize < Dictionary < string , JsonElement > > ( fs ) ?? new ( ) ;
155+ return JsonSerializer . Deserialize < Settings > ( fs ) ?? new ( null , new Dictionary < string , JsonElement > ( ) ) ;
152156 }
153157 catch ( Exception ex )
154158 {
155159 throw new InvalidOperationException ( $ "Failed to load settings from { _settingsFilePath } . The file may be corrupted or malformed. Exception: { ex . Message } ") ;
156160 }
157161 }
162+
163+ [ JsonSerializable ( typeof ( Settings ) ) ]
164+ private class Settings
165+ {
166+ /// <summary>
167+ /// User settings version. Increment this when the settings schema changes.
168+ /// In future iterations we will be able to handle migrations when the user has
169+ /// an older version.
170+ /// </summary>
171+ public int Version { get ; set ; } = 1 ;
172+ public Dictionary < string , JsonElement > Options { get ; set ; }
173+ public Settings ( )
174+ {
175+ Options = new Dictionary < string , JsonElement > ( ) ;
176+ }
177+
178+ public Settings ( int ? version , Dictionary < string , JsonElement > options )
179+ {
180+ Version = version ?? Version ;
181+ Options = options ;
182+ }
183+ }
158184}
0 commit comments