Skip to content

Commit

Permalink
Capture all create directory exceptions to avoid crashes
Browse files Browse the repository at this point in the history
  • Loading branch information
DSPaul committed Sep 18, 2024
1 parent 524f2bf commit 4973526
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 35 deletions.
17 changes: 16 additions & 1 deletion src/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
using COMPASS.Interfaces;
using COMPASS.Models.Enums;
using COMPASS.Services;
using COMPASS.Tools;
using COMPASS.ViewModels;
using System;
using System.IO;
using System.Windows;

Expand All @@ -15,7 +17,20 @@ public partial class App : Application
{
public App()
{
Directory.CreateDirectory(SettingsViewModel.CompassDataPath);
try
{
if (!Directory.Exists(SettingsViewModel.CompassDataPath))
{
Directory.CreateDirectory(SettingsViewModel.CompassDataPath);
}
}
catch (Exception ex)
{
Logger.Error($"Failed to create folder at compass data path, so data cannot be saved", ex);
string msg = $"Failed to create a folder to store user data at {SettingsViewModel.CompassDataPath}, " +
$"please pick a new location to save your data. Creation failed with the following error {ex.Message}";
IOService.AskNewCodexFilePath(msg);
}
}

private static IContainer? _container;
Expand Down
53 changes: 44 additions & 9 deletions src/Models/CodexCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,18 +221,39 @@ public void InitAsNew()

private void CreateDirectories()
{
//top folder
Directory.CreateDirectory(FullDataPath);
//subfolders
Directory.CreateDirectory(CoverArtPath);
Directory.CreateDirectory(ThumbnailsPath);
Directory.CreateDirectory(UserFilesPath);
try
{
//top folder
Directory.CreateDirectory(FullDataPath);
//subfolders
Directory.CreateDirectory(CoverArtPath);
Directory.CreateDirectory(ThumbnailsPath);
Directory.CreateDirectory(UserFilesPath);
}
catch (Exception ex)
{
Logger.Error("Failed to create folders to store user data for this collection.", ex);
var windowedNotificationService = App.Container.ResolveKeyed<INotificationService>(NotificationDisplayType.Windowed);

string msg = $"Failed to create the necessary folders to store data about this collection. The following error occured: {ex.Message}";
Notification failedFolderCreation = new("Failed to save collection", msg, Severity.Error);
windowedNotificationService.Show(failedFolderCreation);
}
}

public void Save()
{
OnPropertyChanged(nameof(AllCodices));
Directory.CreateDirectory(UserFilesPath);

try
{
Directory.CreateDirectory(UserFilesPath);
}
catch (Exception ex)
{
Logger.Error("Failed to create the folder to save the data for this collection", ex);
}

bool savedTags = SaveTags();
bool savedCodices = SaveCodices();
bool savedInfo = SaveInfo();
Expand Down Expand Up @@ -456,7 +477,14 @@ public void ImportCodicesFrom(CodexCollection source)
//if import includes files, make sure directory exists to copy files into
if (Path.Exists(source.UserFilesPath))
{
Directory.CreateDirectory(UserFilesPath);
try
{
Directory.CreateDirectory(UserFilesPath);
}
catch (Exception ex)
{
Logger.Error("Failed to create a folder to store the imported files", ex);
}
}

foreach (var codex in source.AllCodices)
Expand Down Expand Up @@ -508,7 +536,14 @@ public void ImportCodicesFrom(CodexCollection source)
string? newDir = Path.GetDirectoryName(newPath);
if (newDir != null)
{
Directory.CreateDirectory(newDir);
try
{
Directory.CreateDirectory(newDir);
}
catch (Exception ex)
{
Logger.Error("Failed to create a folder to store the imported files", ex);
}
}
File.Copy(codex.Sources.Path, newPath, true);
codex.Sources.Path = newPath;
Expand Down
19 changes: 13 additions & 6 deletions src/Models/Folder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using CommunityToolkit.Mvvm.ComponentModel;
using COMPASS.Tools;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
Expand Down Expand Up @@ -55,13 +57,18 @@ private IEnumerable<Folder> FindSubFolders()
{
if (Directory.Exists(FullPath))
{
var directories = Directory.GetDirectories(FullPath);
return directories.Select(dir => new Folder(dir));
}
else
{
return Enumerable.Empty<Folder>();
try
{
var directories = Directory.GetDirectories(FullPath);
return directories.Select(dir => new Folder(dir));
}
catch (Exception ex)
{
Logger.Error($"Failed to get subfolders of {FullPath}", ex);
}
}

return Enumerable.Empty<Folder>();
}

/// <summary>
Expand Down
28 changes: 28 additions & 0 deletions src/Services/IOService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,34 @@ public static bool TryPickFolders(out string[] selectedPaths)
return null;
}
}

/// <summary>
/// If the exsting codex path is inaccessable for any reason, prompt the user to pick another one
/// </summary>
/// <returns></returns>
public static void AskNewCodexFilePath(string msg)
{
var windowedNotificationService = App.Container.ResolveKeyed<INotificationService>(NotificationDisplayType.Windowed);

Notification pickNewPath = new("Pick a location to save your data", msg, Severity.Warning);
pickNewPath.ConfirmText = "Continue";
windowedNotificationService.Show(pickNewPath);

bool success = false;
while (!success)
{
string? newPath = PickFolder();
if (!string.IsNullOrWhiteSpace(newPath) && Path.Exists(newPath))
{
success = SettingsViewModel.GetInstance().SetNewDataPath(newPath);
}
else
{
Notification notValid = new("Invalid path", $"{newPath} is not a valid path, please try again", Severity.Warning);
windowedNotificationService.Show(notValid);
}
}
}
#endregion

/// <summary>
Expand Down
47 changes: 39 additions & 8 deletions src/ViewModels/CollectionViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,32 @@ public CollectionViewModel(MainViewModel? mainViewModel)
_tagsVM = new(new("__tmp"), _filterVM);

//Create Collections Directory
Directory.CreateDirectory(CodexCollection.CollectionsPath);
try
{
Directory.CreateDirectory(CodexCollection.CollectionsPath);
}
catch (Exception ex)
{
Logger.Error($"Failed to create folder to store user data, so data cannot be saved", ex);
string msg = $"Failed to create a folder to store user data at {SettingsViewModel.CompassDataPath}, " +
$"please pick a new location to save your data. Creation failed with the following error {ex.Message}";
IOService.AskNewCodexFilePath(msg);
}

//Get all collections by folder name
AllCodexCollections = new(Directory
.GetDirectories(CodexCollection.CollectionsPath)
.Select(dir => Path.GetFileName(dir))
.Where(IsLegalCollectionName)
.Select(dir => new CodexCollection(dir)));
try
{
//Get all collections by folder name
AllCodexCollections = new(Directory
.GetDirectories(CodexCollection.CollectionsPath)
.Select(dir => Path.GetFileName(dir))
.Where(IsLegalCollectionName)
.Select(dir => new CodexCollection(dir)));
}
catch (Exception ex)
{
Logger.Error($"Failed to find existing collections in {CodexCollection.CollectionsPath}", ex);
AllCodexCollections = new();
}

LoadInitialCollection();

Expand Down Expand Up @@ -112,7 +130,20 @@ public bool EditCollectionVisibility
#region Methods and Commands
private void LoadInitialCollection()
{
Directory.CreateDirectory(CodexCollection.CollectionsPath);
while (!Directory.Exists(CodexCollection.CollectionsPath))
{
try
{
Directory.CreateDirectory(CodexCollection.CollectionsPath);
}
catch (Exception ex)
{
Logger.Error($"Failed to create folder to store user data, so data cannot be saved", ex);
string msg = $"Failed to create a folder to store user data at {SettingsViewModel.CompassDataPath}, " +
$"please pick a new location to save your data. Creation failed with the following error {ex.Message}";
IOService.AskNewCodexFilePath(msg);
}
}

bool initSuccess = false;
while (!initSuccess)
Expand Down
25 changes: 23 additions & 2 deletions src/ViewModels/Import/ImportFolderViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using COMPASS.Services;
using COMPASS.Tools;
using COMPASS.Windows;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -94,7 +95,17 @@ private List<string> GetPathsToImport()
if (Directory.Exists(currentFolder))
{
NonRecursiveDirectories.Add(currentFolder);
foreach (string dir in Directory.GetDirectories(currentFolder))
IEnumerable<string> subfolders;
try
{
subfolders = Directory.GetDirectories(currentFolder);
}
catch (Exception ex)
{
Logger.Error($"Failed to get subfolders of {currentFolder}", ex);
subfolders = Enumerable.Empty<string>();
}
foreach (string dir in subfolders)
{
toSearch.Enqueue(dir);
}
Expand All @@ -107,7 +118,17 @@ private List<string> GetPathsToImport()
{
if (Directory.Exists(folder))
{
toImport.AddRange(Directory.GetFiles(folder));
IEnumerable<string> files;
try
{
files = Directory.GetFiles(folder);
}
catch (Exception ex)
{
Logger.Error($"Failed to get files of folder {folder}", ex);
files = Enumerable.Empty<string>();
}
toImport.AddRange(files);
}
}

Expand Down
25 changes: 19 additions & 6 deletions src/ViewModels/SettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -461,25 +461,38 @@ private void ChooseNewDataPath()
private RelayCommand? _resetDataPathCommand;
public RelayCommand ResetDataPathCommand => _resetDataPathCommand ??= new(() => SetNewDataPath(_defaultDataPath));

private void SetNewDataPath(string newPath)
public bool SetNewDataPath(string newPath)
{
if (String.IsNullOrWhiteSpace(newPath) || !Path.Exists(newPath)) { return; }
if (String.IsNullOrWhiteSpace(newPath) || !Path.Exists(newPath)) { return false; }

//make sure new folder ends on /COMPASS
string foldername = new DirectoryInfo(newPath).Name;
if (foldername != "COMPASS")
{
newPath = Path.Combine(newPath, "COMPASS");
Directory.CreateDirectory(newPath);
try
{
Directory.CreateDirectory(newPath);
}
catch (Exception ex)
{
Logger.Error($"Failed to create the COMPASS folder at new data path location {newPath}", ex);
return false;
}
}

if (newPath == CompassDataPath) { return; }
if (newPath == CompassDataPath) { return false; }

NewDataPath = newPath;

//Give users choice between moving or copying
ChangeDataLocationWindow window = new(this);
window.ShowDialog();
if (Path.Exists(CompassDataPath))
{
ChangeDataLocationWindow window = new(this);
window.ShowDialog();
}

return true;
}

private AsyncRelayCommand? _moveToNewDataPathCommand;
Expand Down
6 changes: 3 additions & 3 deletions src/Windows/NotificationWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,13 @@
</ItemsControl>

<StackPanel Grid.Row="4" Grid.Column="2" Orientation="Horizontal">
<Button Style="{StaticResource TextButton}" Content="{Binding CancelText}" Margin="5" Padding="3" Width="80" Click="CancelClick"
<Button Style="{StaticResource TextButton}" Content="{Binding CancelText}" Margin="5" Padding="3" MinWidth="80" Click="CancelClick"
Visibility="{Binding Actions, Converter={StaticResource FlagsToVisibilityConverter}, ConverterParameter={x:Static enums:NotificationAction.Cancel}}"
BorderBrush="{StaticResource TextColor}" BorderThickness="2" Background="Transparent"/>
<Button Style="{StaticResource TextButton}" Content="{Binding DeclineText}" Margin="5" Padding="3" Width="80" Click="DeclineClick"
<Button Style="{StaticResource TextButton}" Content="{Binding DeclineText}" Margin="5" Padding="3" MinWidth="80" Click="DeclineClick"
Visibility="{Binding Actions, Converter={StaticResource FlagsToVisibilityConverter}, ConverterParameter={x:Static enums:NotificationAction.Decline}}"
BorderBrush="{StaticResource TextColor}" BorderThickness="2" Background="Transparent"/>
<Button Style="{StaticResource TextButton}" Content="{Binding ConfirmText}" Margin="5" Width="80" Click="ConfirmClick"
<Button Style="{StaticResource TextButton}" Content="{Binding ConfirmText}" Margin="5" MinWidth="80" Click="ConfirmClick"
Visibility="{Binding Actions, Converter={StaticResource FlagsToVisibilityConverter}, ConverterParameter={x:Static enums:NotificationAction.Confirm}}"
Background="{Binding Severity, Converter={StaticResource SeverityToColorConverter}}"
Foreground="{StaticResource Layer0}" IsDefault="True"/>
Expand Down

0 comments on commit 4973526

Please sign in to comment.