2
2
using System . Collections . Generic ;
3
3
using System . IO ;
4
4
using System . Text . Json ;
5
+ using System . Text . Json . Serialization ;
5
6
6
7
namespace Coder . Desktop . App . Services ;
7
8
@@ -28,10 +29,10 @@ public interface ISettingsManager
28
29
public sealed class SettingsManager : ISettingsManager
29
30
{
30
31
private readonly string _settingsFilePath ;
32
+ private Settings _settings ;
31
33
private readonly string _fileName = "app-settings.json" ;
32
34
private readonly string _appName = "CoderDesktop" ;
33
35
private readonly object _lock = new ( ) ;
34
- private Dictionary < string , JsonElement > _cache ;
35
36
36
37
public const string ConnectOnLaunchKey = "ConnectOnLaunch" ;
37
38
public const string StartOnLoginKey = "StartOnLogin" ;
@@ -87,9 +88,12 @@ public SettingsManager(string? settingsFilePath = null)
87
88
// Create the settings file if it doesn't exist
88
89
string emptyJson = JsonSerializer . Serialize ( new { } ) ;
89
90
File . WriteAllText ( _settingsFilePath , emptyJson ) ;
91
+ _settings = new ( ) ;
92
+ }
93
+ else
94
+ {
95
+ _settings = Load ( ) ;
90
96
}
91
-
92
- _cache = Load ( ) ;
93
97
}
94
98
95
99
private void Save ( string name , bool value )
@@ -105,12 +109,12 @@ private void Save(string name, bool value)
105
109
FileShare . None ) ;
106
110
107
111
// 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 ) ;
111
115
fs . Position = 0 ; // Reset stream position to the beginning before writing
112
116
113
- JsonSerializer . Serialize ( fs , _cache , new JsonSerializerOptions { WriteIndented = true } ) ;
117
+ JsonSerializer . Serialize ( fs , _settings , new JsonSerializerOptions { WriteIndented = true } ) ;
114
118
115
119
// This ensures the file is truncated to the new length
116
120
// if the new content is shorter than the old content
@@ -127,7 +131,7 @@ private bool Read(string name, bool defaultValue)
127
131
{
128
132
lock ( _lock )
129
133
{
130
- if ( _cache . TryGetValue ( name , out var element ) )
134
+ if ( _settings . Options . TryGetValue ( name , out var element ) )
131
135
{
132
136
try
133
137
{
@@ -143,16 +147,38 @@ private bool Read(string name, bool defaultValue)
143
147
}
144
148
}
145
149
146
- private Dictionary < string , JsonElement > Load ( )
150
+ private Settings Load ( )
147
151
{
148
152
try
149
153
{
150
154
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 > ( ) ) ;
152
156
}
153
157
catch ( Exception ex )
154
158
{
155
159
throw new InvalidOperationException ( $ "Failed to load settings from{ _settingsFilePath } . The file may be corrupted or malformed. Exception:{ ex . Message } ") ;
156
160
}
157
161
}
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
+ }
158
184
}