Skip to content

Commit 50d13eb

Browse files
committed
feat(Avalonia): import/export/reset config
1 parent 2becb5c commit 50d13eb

3 files changed

Lines changed: 250 additions & 80 deletions

File tree

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,177 @@
1+
using System.Diagnostics;
2+
using Avalonia;
3+
using Avalonia.Controls.ApplicationLifetimes;
4+
using Avalonia.Platform.Storage;
5+
using Avalonia.Threading;
6+
using CommunityToolkit.Mvvm.Input;
7+
using FluentAvalonia.UI.Controls;
8+
using SnapX.Core;
9+
using Xdg.Directories;
10+
111
namespace SnapX.Avalonia.ViewModels;
212

313
public partial class ImportExportVM : ViewModelBase
414
{
15+
[RelayCommand]
16+
public async Task ImportConfig()
17+
{
18+
var topLevel = App.MyMainWindow;
19+
20+
if (topLevel == null)
21+
return;
22+
var startLocation = await topLevel.StorageProvider.TryGetFolderFromPathAsync(
23+
UserDirectory.DocumentsDir
24+
);
25+
var files = await topLevel.StorageProvider.OpenFilePickerAsync(
26+
new FilePickerOpenOptions
27+
{
28+
Title = "Import SnapX Config",
29+
SuggestedStartLocation = startLocation,
30+
AllowMultiple = false,
31+
FileTypeFilter =
32+
[
33+
new FilePickerFileType("SnapX Backup Config")
34+
{
35+
Patterns = ["*.sxb"],
36+
MimeTypes = ["application/octet-stream"],
37+
},
38+
],
39+
}
40+
);
41+
42+
var selectedFile = files.FirstOrDefault();
43+
if (selectedFile != null)
44+
{
45+
var importPath = selectedFile.Path.LocalPath;
46+
DebugHelper.WriteLine($"Import started: {importPath}");
47+
48+
await Task.Run(() =>
49+
{
50+
SettingManager.Import(importPath);
51+
SettingManager.LoadInitialSettings();
52+
});
53+
DebugHelper.WriteLine($"Import completed: {importPath}");
54+
await RestartApp();
55+
}
56+
}
57+
private async Task RestartApp()
58+
{
59+
string message =
60+
"SnapX needs to restart to propagate changes! Hopefully this restart works!";
61+
DebugHelper.WriteLine(message);
62+
63+
var dialog = new ContentDialog
64+
{
65+
Title = "Restart Required",
66+
Content = message + "\n\nRestarting automatically in 5 seconds...",
67+
PrimaryButtonText = "OK",
68+
DefaultButton = ContentDialogButton.Primary,
69+
};
70+
var desktop =
71+
Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime;
72+
73+
if (desktop?.Windows != null)
74+
{
75+
foreach (var win in desktop.Windows)
76+
{
77+
win.IsEnabled = false;
78+
}
79+
}
80+
if (App.MyMainWindow is { } window)
81+
{
82+
// Start a timer to close the dialog automatically
83+
var autoCloseTask = Task.Delay(TimeSpan.FromSeconds(5))
84+
.ContinueWith(_ =>
85+
{
86+
Dispatcher.UIThread.Post(() => dialog.Hide());
87+
});
88+
89+
await dialog.ShowAsync();
90+
}
91+
var processPath = Environment.ProcessPath;
92+
if (string.IsNullOrEmpty(processPath))
93+
return;
94+
95+
var psi = new ProcessStartInfo
96+
{
97+
FileName = processPath,
98+
UseShellExecute = true,
99+
WorkingDirectory = AppContext.BaseDirectory,
100+
};
101+
102+
var args = Environment.GetCommandLineArgs().Skip(1);
103+
foreach (var arg in args)
104+
{
105+
psi.ArgumentList.Add(arg);
106+
}
107+
Process.Start(psi);
108+
109+
foreach (System.Collections.DictionaryEntry de in Environment.GetEnvironmentVariables())
110+
{
111+
var key = de.Key.ToString();
112+
var val = de.Value?.ToString();
113+
if (!string.IsNullOrEmpty(key) && !psi.Environment.ContainsKey(key))
114+
{
115+
psi.EnvironmentVariables[key] = val;
116+
}
117+
}
118+
119+
if (Application.Current?.ApplicationLifetime is IControlledApplicationLifetime lifetime)
120+
{
121+
lifetime.Shutdown(0);
122+
}
123+
else
124+
{
125+
Environment.Exit(0);
126+
}
127+
}
128+
[RelayCommand]
129+
public async Task ExportConfig()
130+
{
131+
var topLevel = App.MyMainWindow;
132+
133+
if (topLevel == null)
134+
return;
135+
var startLocation = await topLevel.StorageProvider.TryGetFolderFromPathAsync(
136+
UserDirectory.DocumentsDir
137+
);
138+
var file = await topLevel.StorageProvider.SaveFilePickerAsync(
139+
new FilePickerSaveOptions
140+
{
141+
Title = "Export SnapX Config",
142+
SuggestedFileName = $"SnapX_Backup_{DateTime.Now:yyyyMMdd}",
143+
SuggestedStartLocation = startLocation,
144+
DefaultExtension = "sxb",
145+
FileTypeChoices =
146+
[
147+
new FilePickerFileType("SnapX Backup Config")
148+
{
149+
Patterns = ["*.sxb"],
150+
MimeTypes = ["application/octet-stream"],
151+
},
152+
],
153+
}
154+
);
155+
156+
if (file != null)
157+
{
158+
var exportPath = file.Path.LocalPath;
159+
DebugHelper.WriteLine($"Export started: {exportPath}");
160+
161+
await Task.Run(() =>
162+
{
163+
SettingManager.Export(exportPath, true, true);
164+
});
5165

166+
DebugHelper.WriteLine($"Export completed: {exportPath}");
167+
await RestartApp();
168+
}
169+
}
170+
[RelayCommand]
171+
public async Task ResetSettings()
172+
{
173+
// Wow, so convenient!
174+
SettingManager.ResetSettings();
175+
await RestartApp();
176+
}
6177
}
Lines changed: 78 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,88 @@
11
<UserControl
2-
d:DesignHeight="450"
3-
d:DesignWidth="800"
4-
mc:Ignorable="d"
5-
x:Class="SnapX.Avalonia.Views.Settings.Views.ImportExportView"
6-
x:DataType="viewModels:ImportExportVM"
7-
xmlns="https://github.com/avaloniaui"
8-
xmlns:avalonia="clr-namespace:FluentIcons.Avalonia;assembly=FluentIcons.Avalonia"
9-
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
10-
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
11-
xmlns:fluent="clr-namespace:FluentIcons.Avalonia.Fluent;assembly=FluentIcons.Avalonia.Fluent"
12-
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
13-
xmlns:viewModels="clr-namespace:SnapX.Avalonia.ViewModels"
14-
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
15-
<Design.DataContext>
16-
<viewModels:ImportExportVM />
17-
</Design.DataContext>
18-
<StackPanel>
19-
<controls:InfoBar
20-
FontWeight="Black"
21-
IsClosable="False"
22-
IsOpen="True"
23-
Margin="16"
24-
Message="This configuration contains passwords, account details, and upload history. Do not share it with someone you do not trust."
25-
Severity="Warning"
26-
Title="Warning">
27-
<controls:InfoBar.IconSource>
28-
<fluent:FluentIconSource
29-
Icon="ShieldPerson"
30-
IconSize="Size48"
31-
IconVariant="Regular" />
32-
</controls:InfoBar.IconSource>
33-
</controls:InfoBar>
34-
<StackPanel
35-
HorizontalAlignment="Center"
36-
Margin="16"
37-
Spacing="16"
38-
VerticalAlignment="Center">
39-
<TextBlock
40-
FontSize="20"
41-
FontWeight="Bold"
42-
HorizontalAlignment="Center"
43-
Text="Configuration" />
2+
x:Class="SnapX.Avalonia.Views.Settings.Views.ImportExportView"
3+
xmlns="https://github.com/avaloniaui"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5+
xmlns:avalonia="clr-namespace:FluentIcons.Avalonia;assembly=FluentIcons.Avalonia"
6+
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
7+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
8+
xmlns:fluent="clr-namespace:FluentIcons.Avalonia.Fluent;assembly=FluentIcons.Avalonia.Fluent"
9+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
10+
xmlns:viewModels="clr-namespace:SnapX.Avalonia.ViewModels"
11+
d:DesignHeight="450"
12+
d:DesignWidth="800"
13+
x:DataType="viewModels:ImportExportVM"
14+
mc:Ignorable="d">
15+
<Design.DataContext>
16+
<viewModels:ImportExportVM />
17+
</Design.DataContext>
18+
<StackPanel>
19+
<controls:InfoBar
20+
Title="Warning"
21+
Margin="16"
22+
FontWeight="Black"
23+
IsClosable="False"
24+
IsOpen="True"
25+
Message="This configuration contains passwords, account details, and upload history. Do not share it with someone you do not trust."
26+
Severity="Warning">
27+
<controls:InfoBar.IconSource>
28+
<fluent:FluentIconSource
29+
Icon="ShieldPerson"
30+
IconSize="Size48"
31+
IconVariant="Regular" />
32+
</controls:InfoBar.IconSource>
33+
</controls:InfoBar>
34+
<StackPanel
35+
Margin="16"
36+
HorizontalAlignment="Center"
37+
VerticalAlignment="Center"
38+
Spacing="16">
39+
<TextBlock
40+
HorizontalAlignment="Center"
41+
FontSize="20"
42+
FontWeight="Bold"
43+
Text="Configuration" />
4444

45+
<StackPanel
46+
HorizontalAlignment="Center"
47+
Orientation="Vertical"
48+
Spacing="12">
49+
<StackPanel
50+
HorizontalAlignment="Center"
51+
Orientation="Vertical"
52+
Spacing="12">
53+
<Button Width="200" Command="{Binding $parent[UserControl].((viewModels:ImportExportVM)DataContext).ImportConfigCommand}">
4554
<StackPanel
46-
HorizontalAlignment="Center"
47-
Orientation="Vertical"
48-
Spacing="12">
49-
<StackPanel
50-
HorizontalAlignment="Center"
51-
Orientation="Vertical"
52-
Spacing="12">
53-
<Button Width="200">
54-
<StackPanel
55-
Orientation="Horizontal"
56-
Spacing="8"
57-
VerticalAlignment="Center">
58-
<avalonia:FluentIcon Icon="ArrowImport" />
59-
<TextBlock Text="Import" />
60-
</StackPanel>
61-
</Button>
62-
63-
<Button Width="200">
64-
<StackPanel
65-
Orientation="Horizontal"
66-
Spacing="8"
67-
VerticalAlignment="Center">
68-
<avalonia:FluentIcon Icon="DocumentDatabase" />
69-
<TextBlock Text="Export" />
70-
</StackPanel>
71-
</Button>
55+
VerticalAlignment="Center"
56+
Orientation="Horizontal"
57+
Spacing="8">
58+
<avalonia:FluentIcon Icon="ArrowImport" />
59+
<TextBlock Text="Import" />
60+
</StackPanel>
61+
</Button>
7262

73-
<Button Width="200">
74-
<StackPanel
75-
Orientation="Horizontal"
76-
Spacing="8"
77-
VerticalAlignment="Center">
78-
<avalonia:FluentIcon Icon="DatabaseWarning" />
79-
<TextBlock Text="Reset" />
80-
</StackPanel>
81-
</Button>
82-
</StackPanel>
63+
<Button Width="200" Command="{Binding $parent[UserControl].((viewModels:ImportExportVM)DataContext).ExportConfigCommand}">
64+
<StackPanel
65+
VerticalAlignment="Center"
66+
Orientation="Horizontal"
67+
Spacing="8">
68+
<avalonia:FluentIcon Icon="DocumentDatabase" />
69+
<TextBlock Text="Export" />
70+
</StackPanel>
71+
</Button>
8372

73+
<Button Width="200" Command="{Binding $parent[UserControl].((viewModels:ImportExportVM)DataContext).ResetSettingsCommand}">
74+
<StackPanel
75+
VerticalAlignment="Center"
76+
Orientation="Horizontal"
77+
Spacing="8">
78+
<avalonia:FluentIcon Icon="DatabaseWarning" />
79+
<TextBlock Text="Reset" />
8480
</StackPanel>
81+
</Button>
8582
</StackPanel>
83+
84+
</StackPanel>
8685
</StackPanel>
86+
</StackPanel>
8787

8888
</UserControl>
89-

SnapX.Avalonia/Views/Settings/Views/ImportExportView.axaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ public partial class ImportExportView : UserControl
88
private readonly ImportExportVM _vm;
99
public ImportExportView(ImportExportVM vm)
1010
{
11+
InitializeComponent();
1112
_vm = vm;
1213
DataContext = _vm;
13-
InitializeComponent();
1414
}
1515

1616
public ImportExportView() : this(new ImportExportVM())

0 commit comments

Comments
 (0)