@@ -134,9 +134,144 @@ private void OnResetGradient_Click(object sender, RoutedEventArgs e)
134134 if ( DataContext is not AppearanceViewModel vm ) return ;
135135
136136 vm . ResetGradientStops ( ) ;
137+ vm . GradientAngle = 0 ;
137138 UpdateGradientTheme ( ) ;
138139 }
139140
141+ private void OnExportGradient_Click ( object sender , RoutedEventArgs e )
142+ {
143+ if ( DataContext is not AppearanceViewModel vm ) return ;
144+
145+ var saveDialog = new SaveFileDialog
146+ {
147+ Filter = "JSON Files (*.json)|*.json|Text Files (*.txt)|*.txt" ,
148+ DefaultExt = ".json" ,
149+ FileName = "Froststrap Gradient Background"
150+ } ;
151+
152+ if ( saveDialog . ShowDialog ( ) == true )
153+ {
154+ try
155+ {
156+ var gradientData = new
157+ {
158+ GradientStops = vm . GradientStops . Select ( gs => new { gs . Offset , gs . Color } ) . ToList ( ) ,
159+ GradientAngle = vm . GradientAngle ,
160+ Version = App . Version
161+ } ;
162+
163+ string json = JsonSerializer . Serialize ( gradientData , new JsonSerializerOptions
164+ {
165+ WriteIndented = true
166+ } ) ;
167+
168+ File . WriteAllText ( saveDialog . FileName , json ) ;
169+
170+ Frontend . ShowMessageBox (
171+ "Gradient exported successfully!" ,
172+ MessageBoxImage . Information ,
173+ MessageBoxButton . OK
174+ ) ;
175+ }
176+ catch ( Exception ex )
177+ {
178+ Frontend . ShowMessageBox (
179+ $ "Failed to export gradient: { ex . Message } ",
180+ MessageBoxImage . Error ,
181+ MessageBoxButton . OK
182+ ) ;
183+ }
184+ }
185+ }
186+
187+ private void OnImportGradient_Click ( object sender , RoutedEventArgs e )
188+ {
189+ if ( DataContext is not AppearanceViewModel vm ) return ;
190+
191+ var openDialog = new OpenFileDialog
192+ {
193+ Filter = "JSON Files (*.json)|*.json|Text Files (*.txt)|*.txt" ,
194+ Multiselect = false
195+ } ;
196+
197+ if ( openDialog . ShowDialog ( ) == true )
198+ {
199+ try
200+ {
201+ string json = File . ReadAllText ( openDialog . FileName ) ;
202+ using var document = JsonDocument . Parse ( json ) ;
203+ var root = document . RootElement ;
204+
205+ if ( ! root . TryGetProperty ( "GradientStops" , out var stopsElement ) ||
206+ stopsElement . GetArrayLength ( ) == 0 )
207+ {
208+ throw new InvalidDataException ( "Invalid gradient file format." ) ;
209+ }
210+
211+ var gradientStops = new List < GradientStops > ( ) ;
212+ foreach ( var stopElement in stopsElement . EnumerateArray ( ) )
213+ {
214+ if ( stopElement . TryGetProperty ( "Offset" , out var offsetElement ) &&
215+ stopElement . TryGetProperty ( "Color" , out var colorElement ) &&
216+ offsetElement . ValueKind == JsonValueKind . Number &&
217+ colorElement . ValueKind == JsonValueKind . String )
218+ {
219+ var offset = offsetElement . GetDouble ( ) ;
220+ var color = colorElement . GetString ( ) ! ;
221+
222+ if ( offset < 0 || offset > 1 || ! IsValidHexColor ( color ) )
223+ {
224+ throw new InvalidDataException ( "Invalid gradient stop data." ) ;
225+ }
226+
227+ gradientStops . Add ( new GradientStops { Offset = offset , Color = color } ) ;
228+ }
229+ else
230+ {
231+ throw new InvalidDataException ( "Invalid gradient stop format." ) ;
232+ }
233+ }
234+
235+ double gradientAngle = vm . GradientAngle ;
236+ if ( root . TryGetProperty ( "GradientAngle" , out var angleElement ) &&
237+ angleElement . ValueKind == JsonValueKind . Number )
238+ {
239+ var angle = angleElement . GetDouble ( ) ;
240+ if ( angle >= 0 && angle <= 360 )
241+ {
242+ gradientAngle = angle ;
243+ }
244+ }
245+
246+ vm . GradientStops . Clear ( ) ;
247+ foreach ( var stop in gradientStops )
248+ {
249+ vm . GradientStops . Add ( stop ) ;
250+ }
251+
252+ vm . GradientAngle = gradientAngle ;
253+ App . Settings . Prop . CustomGradientStops = vm . GradientStops . ToList ( ) ;
254+ App . Settings . Prop . GradientAngle = gradientAngle ;
255+
256+ UpdateGradientTheme ( ) ;
257+
258+ Frontend . ShowMessageBox (
259+ "Gradient imported successfully!" ,
260+ MessageBoxImage . Information ,
261+ MessageBoxButton . OK
262+ ) ;
263+ }
264+ catch ( Exception ex )
265+ {
266+ Frontend . ShowMessageBox (
267+ $ "Failed to import gradient: { ex . Message } ",
268+ MessageBoxImage . Error ,
269+ MessageBoxButton . OK
270+ ) ;
271+ }
272+ }
273+ }
274+
140275 private static bool IsValidHexColor ( string color ) => ! string . IsNullOrWhiteSpace ( color ) && color . StartsWith ( "#" ) && color . Length >= 7 ;
141276
142277 private void MoveUp_Click ( object sender , RoutedEventArgs e )
0 commit comments