Skip to content

Commit

Permalink
Should fix #440
Browse files Browse the repository at this point in the history
  • Loading branch information
bcssov committed May 12, 2023
1 parent 73c7239 commit 8660bc5
Show file tree
Hide file tree
Showing 3 changed files with 234 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// ***********************************************************************
// Assembly : IronyModManager.Platform
// Author : Avalonia
// Created : 05-12-2023
//
// Last Modified By : Mario
// Last Modified On : 05-12-2023
// ***********************************************************************
// <copyright file="WindowsMountedVolumeInfoListener.cs" company="Avalonia">
// Avalonia
// </copyright>
// <summary>Literally copied to fix a CTD as described here: https:github.com/AvaloniaUI/Avalonia/issues/8437.</summary>
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using Avalonia.Controls.Platform;
using Avalonia.Logging;

namespace IronyModManager.Platform.Drives
{
/// <summary>
/// Class WindowsMountedVolumeInfoListener.
/// Implements the <see cref="IDisposable" />
/// </summary>
/// <seealso cref="IDisposable" />
internal class WindowsMountedVolumeInfoListener : IDisposable
{
#region Fields

/// <summary>
/// The disposables
/// </summary>
private readonly CompositeDisposable disposables;

/// <summary>
/// The been disposed
/// </summary>
private bool beenDisposed = false;

/// <summary>
/// The mounted drives
/// </summary>
private readonly ObservableCollection<MountedVolumeInfo> mountedDrives;

#endregion Fields

#region Constructors

/// <summary>
/// Initializes a new instance of the <see cref="WindowsMountedVolumeInfoListener" /> class.
/// </summary>
/// <param name="mountedDrives">The mounted drives.</param>
public WindowsMountedVolumeInfoListener(ObservableCollection<MountedVolumeInfo> mountedDrives)
{
this.mountedDrives = mountedDrives;
disposables = new CompositeDisposable();

var pollTimer = Observable.Interval(TimeSpan.FromSeconds(1))
.Subscribe(Poll);

disposables.Add(pollTimer);

Poll(0);
}

#endregion Constructors

#region Methods

/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
}

/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (!beenDisposed)
{
if (disposing)
{
}
beenDisposed = true;
}
}

/// <summary>
/// Polls the specified .
/// </summary>
/// <param name="_">The .</param>
private void Poll(long _)
{
var allDrives = DriveInfo.GetDrives();

var mountVolInfos = allDrives
.Where(p =>
{
try
{
var ret = p.IsReady;
return ret;
}
catch (Exception e)
{
Logger.TryGet(LogEventLevel.Warning, LogArea.Control)?.Log(this, $"Error in Windows drive enumeration: {e.Message}");
}
return false;
})
.Select(ParseDrive)
.Where(p => p.IsValid)
.ToArray();

if (mountedDrives.SequenceEqual(mountVolInfos))
return;
else
{
mountedDrives.Clear();

foreach (var i in mountVolInfos)
mountedDrives.Add(i);
}
}

/// <summary>
/// Parses the drive.
/// </summary>
/// <param name="drive">The drive.</param>
/// <returns>IronyModManager.Platform.Drives.SafeMountedVolumeInfo.</returns>
private SafeMountedVolumeInfo ParseDrive(DriveInfo drive)
{
try
{
return new SafeMountedVolumeInfo()
{
VolumeLabel = string.IsNullOrEmpty(drive.VolumeLabel.Trim()) ? drive.RootDirectory.FullName
: $"{drive.VolumeLabel} ({drive.Name})",
VolumePath = drive.RootDirectory.FullName,
VolumeSizeBytes = (ulong)drive.TotalSize,
IsValid = true
};
}
catch (Exception ex)
{
Logger.TryGet(LogEventLevel.Warning, LogArea.Control)?.Log(this, $"Error in Windows drive enumeration, drive probably not ready: {ex.Message}");
return new SafeMountedVolumeInfo()
{
IsValid = false
};
}
}

/// <summary>
/// Class SafeMountedVolumeInfo.
/// Implements the <see cref="MountedVolumeInfo" />
/// </summary>
/// <seealso cref="MountedVolumeInfo" />
private class SafeMountedVolumeInfo : MountedVolumeInfo
{
/// <summary>
/// Returns true if ... is valid.
/// </summary>
/// <value>The is valid.</value>
public bool IsValid { get; set; }
}
}

#endregion Methods
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// ***********************************************************************
// Assembly : IronyModManager.Platform
// Author : Avalonia
// Created : 05-12-2023
//
// Last Modified By : Mario
// Last Modified On : 05-12-2023
// ***********************************************************************
// <copyright file="WindowsMountedVolumeInfoProvider.cs" company="Avalonia">
// Avalonia
// </copyright>
// <summary></summary>
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Avalonia;
using Avalonia.Controls.Platform;

namespace IronyModManager.Platform.Drives
{
/// <summary>
/// Class WindowsMountedVolumeInfoProvider.
/// Implements the <see cref="IMountedVolumeInfoProvider" />
/// </summary>
/// <seealso cref="IMountedVolumeInfoProvider" />
public class WindowsMountedVolumeInfoProvider : IMountedVolumeInfoProvider
{
#region Methods

/// <summary>
/// Listens to any changes in volume mounts and
/// forwards updates to the referenced
/// <see cref="T:System.Collections.ObjectModel.ObservableCollection`1" />.
/// </summary>
/// <param name="mountedDrives">The mounted drives.</param>
/// <returns>IDisposable.</returns>
public IDisposable Listen(ObservableCollection<MountedVolumeInfo> mountedDrives)
{
Contract.Requires<ArgumentNullException>(mountedDrives != null);
return new WindowsMountedVolumeInfoListener(mountedDrives);
}

#endregion Methods
}
}
9 changes: 8 additions & 1 deletion src/IronyModManager.Platform/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Created : 10-29-2020
//
// Last Modified By : Mario
// Last Modified On : 11-24-2022
// Last Modified On : 05-12-2023
// ***********************************************************************
// <copyright file="Extensions.cs" company="Mario">
// Mario
Expand All @@ -15,13 +15,15 @@
using System.Collections.Generic;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Platform;
using IronyModManager.DI;
using IronyModManager.Platform.Assets;
using IronyModManager.Platform.Clipboard;
using IronyModManager.Platform.Configuration;
using IronyModManager.Platform.Drives;
using IronyModManager.Platform.Fonts;
using IronyModManager.Shared;

Expand Down Expand Up @@ -91,6 +93,11 @@ public static TAppBuilder UseIronyPlatformDetect<TAppBuilder>(this TAppBuilder b
// Input manager
var inputManager = AvaloniaLocator.Current.GetService<IInputManager>();
AvaloniaLocator.CurrentMutable.Bind<IInputManager>().ToConstant(new InputManager.InputManager(inputManager));
// Windows only
if (os == OperatingSystemType.WinNT)
{
AvaloniaLocator.CurrentMutable.Bind<IMountedVolumeInfoProvider>().ToConstant(new WindowsMountedVolumeInfoProvider());
}
});
return builder;
}
Expand Down

0 comments on commit 8660bc5

Please sign in to comment.