Skip to content

Commit 1954b1f

Browse files
committed
Implement asking for a backup and loading it into package bundles
1 parent 2a96d01 commit 1954b1f

3 files changed

Lines changed: 85 additions & 136 deletions

File tree

src/UniGetUI/Pages/DialogPages/DialogHelper_Generic.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,4 +624,42 @@ public static void ShowDismissableBalloon(string title, string message)
624624
Window.DismissableNotification.Content = new TextBlock() { Text = message, TextWrapping = TextWrapping.Wrap };
625625
Window.DismissableNotification.IsOpen = true;
626626
}
627+
628+
public static async Task<string?> AskForBackupSelection(IEnumerable<string> availableBackups)
629+
{
630+
var dialog = DialogFactory.Create();
631+
dialog.Title = CoreTools.Translate("Which backup do you want to open?");
632+
dialog.PrimaryButtonText = CoreTools.Translate("Open");
633+
dialog.SecondaryButtonText = CoreTools.Translate("Cancel");
634+
dialog.DefaultButton = ContentDialogButton.Primary;
635+
dialog.IsPrimaryButtonEnabled = false;
636+
637+
RadioButtons buttons = new RadioButtons();
638+
foreach(var name in availableBackups) buttons.Items.Add(name);
639+
buttons.SelectionChanged += (_, _) => dialog.IsPrimaryButtonEnabled = true;
640+
641+
dialog.Content = new StackPanel()
642+
{
643+
Orientation = Orientation.Vertical,
644+
Spacing = 4,
645+
Children =
646+
{
647+
new TextBlock() {
648+
Text = CoreTools.Translate(
649+
"Select the backup you want to open. Later, you will be able to review which packages you want to install."),
650+
TextWrapping = TextWrapping.Wrap
651+
},
652+
new ScrollViewer()
653+
{
654+
Content = buttons,
655+
HorizontalScrollMode = ScrollMode.Disabled
656+
}
657+
}
658+
};
659+
660+
if(await Window.ShowDialogAsync(dialog) is ContentDialogResult.Primary)
661+
return buttons.SelectedItem.ToString() ?? null;
662+
663+
return null;
664+
}
627665
}

src/UniGetUI/Pages/SettingsPages/GeneralPages/Backup.xaml.cs

Lines changed: 26 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -94,79 +94,48 @@ private async void UpdateBackupToGitHubButtonStatus()
9494
RestorePackagesFromGitHubButton.IsEnabled = isAuthenticated;
9595
}
9696

97-
/*private async void RestoreSettingsFromGitHubButton_Click(object sender, EventArgs e)
98-
{
99-
RestoreSettingsFromGitHubButton.IsEnabled = false;
100-
var confirmDialog = DialogHelper.DialogFactory.Create();
101-
confirmDialog.Title = CoreTools.Translate("Confirm Restore");
102-
confirmDialog.Content = CoreTools.Translate("Restoring settings from GitHub Gist will overwrite your current local settings. Are you sure you want to continue?");
103-
confirmDialog.PrimaryButtonText = CoreTools.Translate("Yes, Restore");
104-
confirmDialog.CloseButtonText = CoreTools.Translate("Cancel");
105-
confirmDialog.DefaultButton = ContentDialogButton.Close;
106-
107-
var result = await DialogHelper.Window.ShowDialogAsync(confirmDialog);
108-
if (result != ContentDialogResult.Primary)
109-
{
110-
UpdateBackupToGitHubButtonStatus();
111-
return;
112-
}
113-
114-
DialogHelper.ShowLoadingDialog(CoreTools.Translate("Restoring settings from GitHub Gist..."));
115-
var settingsContent = "";//await _backupService.RetrieveFileAsync("unigetui.settings.json");
116-
if (settingsContent != null)
117-
{
118-
await Task.Run(() => Settings.ImportFromString_JSON(settingsContent));
119-
DialogHelper.HideLoadingDialog();
120-
Logger.Info("Successfully restored settings from GitHub Gist.");
121-
DialogHelper.ShowDismissableBalloon(
122-
CoreTools.Translate("Restore Successful"),
123-
CoreTools.Translate("Your settings have been successfully restored from GitHub Gist. A restart is recommended to apply all changes."));
124-
}
125-
else
126-
{
127-
DialogHelper.HideLoadingDialog();
128-
Logger.Error("Failed to restore settings from GitHub Gist.");
129-
var errorDialog = DialogHelper.DialogFactory.Create();
130-
errorDialog.Title = CoreTools.Translate("Restore Failed");
131-
errorDialog.Content = CoreTools.Translate("Could not restore settings from GitHub Gist. Please check the logs for more details, or ensure a backup exists.");
132-
errorDialog.PrimaryButtonText = CoreTools.Translate("OK");
133-
errorDialog.DefaultButton = ContentDialogButton.Primary;
134-
_ = DialogHelper.Window.ShowDialogAsync(errorDialog);
135-
}
136-
UpdateBackupToGitHubButtonStatus();
137-
}*/
138-
13997
private async void RestorePackagesFromGitHubButton_Click(object sender, EventArgs e)
14098
{
14199
RestorePackagesFromGitHubButton.IsEnabled = false;
142100
try
143101
{
144-
var b = await _backupService.GetAvailableBackups();
102+
DialogHelper.ShowLoadingDialog(CoreTools.Translate("Fetching available backups..."));
103+
var availableBackups = await _backupService.GetAvailableBackups();
104+
DialogHelper.HideLoadingDialog();
145105

146-
var errorDialog = DialogHelper.DialogFactory.Create();
147-
errorDialog.Title = CoreTools.Translate("Select backup:");
148-
errorDialog.Content = CoreTools.Translate(" - " + (string.Join("\n - ", b)));
149-
errorDialog.PrimaryButtonText = CoreTools.Translate("OK");
150-
errorDialog.DefaultButton = ContentDialogButton.Primary;
151-
await DialogHelper.Window.ShowDialogAsync(errorDialog);
152-
RestorePackagesFromGitHubButton.IsEnabled = true;
153-
return;
106+
var selectedBackup = await DialogHelper.AskForBackupSelection(availableBackups);
107+
if (selectedBackup is null)
108+
{
109+
RestorePackagesFromGitHubButton.IsEnabled = true;
110+
return;
111+
}
112+
selectedBackup = selectedBackup.Split(' ')[0];
154113

114+
DialogHelper.ShowLoadingDialog(CoreTools.Translate("Downloading backup..."));
115+
var backupContents = await _backupService.GetBackupContents(selectedBackup);
116+
DialogHelper.HideLoadingDialog();
117+
await Task.Delay(500); // Prevent race conditions with dialogs
155118

156-
MainApp.Instance.MainWindow.NavigationPage.LoadBundleFromString("", BundleFormatType.UBUNDLE, "GitHub Gist");
119+
if (backupContents is null)
120+
throw new Exception($"The backupContents for backup {selectedBackup} returned null");
157121

158122
Logger.Info("Successfully loaded package bundle from GitHub Gist.");
159123
DialogHelper.ShowDismissableBalloon(
160-
CoreTools.Translate("Backup loaded successfully!"),
161-
CoreTools.Translate("The package bundle has been loaded into the Package Bundles page."));
124+
CoreTools.Translate("Done!"),
125+
CoreTools.Translate("The cloud backup has been loaded successfully."));
126+
127+
MainApp.Instance.MainWindow.NavigationPage.LoadBundleFromString(
128+
backupContents, BundleFormatType.UBUNDLE, $"GitHub Gist {selectedBackup}");
162129
}
163130
catch (Exception ex)
164131
{
132+
Logger.Error("An error occurred while loading a backup:");
133+
Logger.Error(ex);
134+
165135
DialogHelper.HideLoadingDialog();
166-
Logger.Error("Failed to restore packages from GitHub Gist.");
167136
var errorDialog = DialogHelper.DialogFactory.Create();
168-
errorDialog.Title = CoreTools.Translate("Restore Failed");
169-
errorDialog.Content = CoreTools.Translate("Could not restore packages from GitHub Gist. Please check the logs for more details, or ensure a backup exists.");
137+
errorDialog.Title = CoreTools.Translate("An error occurred");
138+
errorDialog.Content = CoreTools.Translate("An error occurred while loading a backup: ") + ex.Message;
170139
errorDialog.PrimaryButtonText = CoreTools.Translate("OK");
171140
errorDialog.DefaultButton = ContentDialogButton.Primary;
172141
await DialogHelper.Window.ShowDialogAsync(errorDialog);

src/UniGetUI/Services/GitHubBackupService.cs

Lines changed: 21 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -137,87 +137,29 @@ public async Task<IEnumerable<string>> GetAvailableBackups()
137137
.Select(f => $"{f.Key.Split(' ')[^1]} ({CoreTools.FormatAsSize(f.Value.Size)})") ?? [];
138138
}
139139

140-
141-
/*public async Task<string?> RetrieveFileAsync(string fileName)
140+
/// <summary>
141+
/// For the given backupName, retrieve the backup contents
142+
/// </summary>
143+
/// <param name="backupName"></param>
144+
/// <returns></returns>
145+
/// <exception cref="Exception"></exception>
146+
public async Task<string?> GetBackupContents(string backupName)
142147
{
143-
var client = await CreateClientAsync();
144-
if (client == null) return null;
148+
var GHClient = await CreateClientAsync();
149+
if (GHClient is null)
150+
throw new Exception("The GitHub user is not authenticated");
145151

146-
string fileContent = null;
147-
string gistId = Settings.GetValue(Settings.K.GitHubGistId);
152+
User user = await GHClient.User.Current();
148153

149-
try
150-
{
151-
if (!string.IsNullOrEmpty(gistId))
152-
{
153-
try
154-
{
155-
var gist = await client.Gist.Get(gistId);
156-
if (gist.Files.TryGetValue(fileName, out var file) && file != null)
157-
{
158-
fileContent = file.Content;
159-
Logger.Info($"Successfully retrieved file '{fileName}' content from Gist ID: {gistId}");
160-
}
161-
else
162-
{
163-
Logger.Error($"Gist ID {gistId} does not contain the expected file: {fileName}");
164-
}
165-
}
166-
catch (NotFoundException)
167-
{
168-
Logger.Warn($"Stored Gist ID {gistId} not found. Will try to find by description.");
169-
Settings.SetValue(Settings.K.GitHubGistId, "");
170-
gistId = null;
171-
}
172-
catch (Exception ex)
173-
{
174-
Logger.Error($"Error fetching Gist ID {gistId}: {ex.Message}. Will try to find by description.");
175-
Settings.SetValue(Settings.K.GitHubGistId, "");
176-
gistId = null;
177-
}
178-
}
179-
180-
if (fileContent == null)
181-
{
182-
Logger.Info("Attempting to find settings Gist by description...");
183-
var gists = await client.Gist.GetAll();
184-
var settingsGist = gists.FirstOrDefault(g => g.Description == GistDescription && g.Files.ContainsKey(fileName));
185-
186-
if (settingsGist != null)
187-
{
188-
var fullGist = await client.Gist.Get(settingsGist.Id);
189-
if (fullGist.Files.TryGetValue(fileName, out var file) && file != null)
190-
{
191-
fileContent = file.Content;
192-
Settings.SetValue(Settings.K.GitHubGistId, fullGist.Id);
193-
Logger.Info($"Found settings Gist by description. ID: {fullGist.Id}");
194-
}
195-
else
196-
{
197-
Logger.Error($"Found Gist by description (ID: {settingsGist.Id}) but it's missing file {fileName}.");
198-
}
199-
}
200-
else
201-
{
202-
Logger.Warn($"No UniGetUI settings Gist found for the user with file {fileName}.");
203-
return null;
204-
}
205-
}
206-
207-
if (string.IsNullOrEmpty(fileContent))
208-
{
209-
Logger.Error($"File content for '{fileName}' is empty or could not be retrieved from Gist.");
210-
return null;
211-
}
212-
213-
return fileContent;
214-
}
215-
catch (Exception ex)
216-
{
217-
Logger.Error($"Failed to restore file '{fileName}' from GitHub Gist:");
218-
Logger.Error(ex);
219-
return null;
220-
}
221-
}*/
154+
var candidates = await GHClient.Gist.GetAllForUser(user.Login);
155+
Gist? existingBackup = candidates.FirstOrDefault(g => g.Description.EndsWith(GistDescription_EndingKey));
156+
if (existingBackup is null)
157+
throw new Exception($"The backup {backupName} was not found");
158+
159+
existingBackup = await GHClient.Gist.Get(existingBackup.Id);
160+
return existingBackup.Files
161+
.FirstOrDefault(f => f.Key.StartsWith(PackageBackup_StartingKey) && f.Key.EndsWith(backupName))
162+
.Value.Content;
163+
}
222164
}
223165
}

0 commit comments

Comments
 (0)