Compare commits

..

3 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
94ec17d62a Fix startup crash by adding safe wrappers for assembly location access
Co-authored-by: emako <24737061+emako@users.noreply.github.com>
2025-08-12 02:01:11 +00:00
Copilot
a5241251d4 Initial plan 2025-08-12 01:49:28 +00:00
ema
14a5bea926 Code Cleanup
Some checks failed
MSBuild / build (push) Has been cancelled
MSBuild / publish (push) Has been cancelled
2025-08-09 00:38:43 +08:00
13 changed files with 197 additions and 204 deletions

View File

@@ -45,7 +45,7 @@ public class ArchiveFileEntry : IComparable<ArchiveFileEntry>
public DateTime ModifiedDate { get; set; } public DateTime ModifiedDate { get; set; }
/// <summary> /// <summary>
/// Returns the maximum depth of all siblings /// Returns the maximum depth of all siblings
/// </summary> /// </summary>
public int Level public int Level
{ {
@@ -75,7 +75,7 @@ public class ArchiveFileEntry : IComparable<ArchiveFileEntry>
} }
/// <summary> /// <summary>
/// Returns the number of nodes in the longest path to a leaf /// Returns the number of nodes in the longest path to a leaf
/// </summary> /// </summary>
private int GetDepth() private int GetDepth()
{ {

View File

@@ -28,9 +28,9 @@ using System.Windows.Media.Imaging;
namespace QuickLook.Plugin.ArchiveViewer; namespace QuickLook.Plugin.ArchiveViewer;
/// <summary> /// <summary>
/// Internals are mostly from here: /// Internals are mostly from here:
/// http://www.codeproject.com/Articles/2532/Obtaining-and-managing-file-and-folder-icons-using /// http://www.codeproject.com/Articles/2532/Obtaining-and-managing-file-and-folder-icons-using
/// Caches all results. /// Caches all results.
/// </summary> /// </summary>
public static class IconManager public static class IconManager
{ {
@@ -48,7 +48,7 @@ public static class IconManager
} }
/// <summary> /// <summary>
/// Get the icon of a directory /// Get the icon of a directory
/// </summary> /// </summary>
/// <param name="large">16x16 or 32x32 icon</param> /// <param name="large">16x16 or 32x32 icon</param>
/// <returns>an icon</returns> /// <returns>an icon</returns>
@@ -68,7 +68,7 @@ public static class IconManager
} }
/// <summary> /// <summary>
/// Get an icon for a given filename /// Get an icon for a given filename
/// </summary> /// </summary>
/// <param name="fileName">any filename</param> /// <param name="fileName">any filename</param>
/// <param name="large">16x16 or 32x32 icon</param> /// <param name="large">16x16 or 32x32 icon</param>
@@ -89,7 +89,7 @@ public static class IconManager
} }
/// <summary> /// <summary>
/// http://stackoverflow.com/a/6580799/1943849 /// http://stackoverflow.com/a/6580799/1943849
/// </summary> /// </summary>
private static ImageSource ToImageSource(this Icon icon) private static ImageSource ToImageSource(this Icon icon)
{ {
@@ -101,31 +101,31 @@ public static class IconManager
} }
/// <summary> /// <summary>
/// Provides static methods to read system icons for both folders and files. /// Provides static methods to read system icons for both folders and files.
/// </summary> /// </summary>
/// <example> /// <example>
/// <code>IconReader.GetFileIcon("c:\\general.xls");</code> /// <code>IconReader.GetFileIcon("c:\\general.xls");</code>
/// </example> /// </example>
private static class IconReader private static class IconReader
{ {
/// <summary> /// <summary>
/// Options to specify the size of icons to return. /// Options to specify the size of icons to return.
/// </summary> /// </summary>
public enum IconSize public enum IconSize
{ {
/// <summary> /// <summary>
/// Specify large icon - 32 pixels by 32 pixels. /// Specify large icon - 32 pixels by 32 pixels.
/// </summary> /// </summary>
Large = 0, Large = 0,
/// <summary> /// <summary>
/// Specify small icon - 16 pixels by 16 pixels. /// Specify small icon - 16 pixels by 16 pixels.
/// </summary> /// </summary>
Small = 1 Small = 1
} }
/// <summary> /// <summary>
/// Returns the icon of a folder. /// Returns the icon of a folder.
/// </summary> /// </summary>
/// <param name="size">Large or small</param> /// <param name="size">Large or small</param>
/// <param name="linkOverlay">Whether to include the link icon</param> /// <param name="linkOverlay">Whether to include the link icon</param>
@@ -152,7 +152,7 @@ public static class IconManager
} }
/// <summary> /// <summary>
/// Returns an icon for a given file - indicated by the name parameter. /// Returns an icon for a given file - indicated by the name parameter.
/// </summary> /// </summary>
/// <param name="name">Pathname for file.</param> /// <param name="name">Pathname for file.</param>
/// <param name="size">Large or small</param> /// <param name="size">Large or small</param>
@@ -181,8 +181,8 @@ public static class IconManager
} }
/// <summary> /// <summary>
/// Wraps necessary Shell32.dll structures and functions required to retrieve Icon Handles using SHGetFileInfo. Code /// Wraps necessary Shell32.dll structures and functions required to retrieve Icon Handles using SHGetFileInfo. Code
/// courtesy of MSDN Cold Rooster Consulting case study. /// courtesy of MSDN Cold Rooster Consulting case study.
/// </summary> /// </summary>
private static class Shell32 private static class Shell32
{ {
@@ -221,13 +221,13 @@ public static class IconManager
} }
/// <summary> /// <summary>
/// Wraps necessary functions imported from User32.dll. Code courtesy of MSDN Cold Rooster Consulting example. /// Wraps necessary functions imported from User32.dll. Code courtesy of MSDN Cold Rooster Consulting example.
/// </summary> /// </summary>
private static class User32 private static class User32
{ {
/// <summary> /// <summary>
/// Provides access to function required to delete handle. This method is used internally /// Provides access to function required to delete handle. This method is used internally
/// and is not required to be called separately. /// and is not required to be called separately.
/// </summary> /// </summary>
/// <param name="hIcon">Pointer to icon handle.</param> /// <param name="hIcon">Pointer to icon handle.</param>
/// <returns>N/A</returns> /// <returns>N/A</returns>

View File

@@ -8,16 +8,16 @@ using System.Xml.Serialization;
namespace RegFileParser; namespace RegFileParser;
/// <summary> /// <summary>
/// The main reg file parsing class. /// The main reg file parsing class.
/// Reads the given reg file and stores the content as /// Reads the given reg file and stores the content as
/// a Dictionary of registry keys and values as a Dictionary of registry values <see cref="RegValueObject" /> /// a Dictionary of registry keys and values as a Dictionary of registry values <see cref="RegValueObject" />
/// </summary> /// </summary>
public class RegFileObject public class RegFileObject
{ {
#region Public Properties #region Public Properties
/// <summary> /// <summary>
/// Gets the dictionary containing all entries /// Gets the dictionary containing all entries
/// </summary> /// </summary>
public Dictionary<string, Dictionary<string, RegValueObject>> RegValues => regvalues; public Dictionary<string, Dictionary<string, RegValueObject>> RegValues => regvalues;
@@ -26,12 +26,12 @@ public class RegFileObject
#region Private Fields #region Private Fields
/// <summary> /// <summary>
/// Raw content of the reg file /// Raw content of the reg file
/// </summary> /// </summary>
private string content; private string content;
/// <summary> /// <summary>
/// the dictionary containing parsed registry values /// the dictionary containing parsed registry values
/// </summary> /// </summary>
private readonly Dictionary<string, Dictionary<string, RegValueObject>> regvalues; private readonly Dictionary<string, Dictionary<string, RegValueObject>> regvalues;
@@ -61,7 +61,7 @@ public class RegFileObject
#region Private Methods #region Private Methods
/// <summary> /// <summary>
/// Imports the reg file /// Imports the reg file
/// </summary> /// </summary>
public void Read(string path) public void Read(string path)
{ {
@@ -70,7 +70,7 @@ public class RegFileObject
} }
/// <summary> /// <summary>
/// Imports the reg file /// Imports the reg file
/// </summary> /// </summary>
public void Read(byte[] bytes) public void Read(byte[] bytes)
{ {
@@ -109,7 +109,7 @@ public class RegFileObject
} }
/// <summary> /// <summary>
/// Parses the reg file for reg keys and reg values /// Parses the reg file for reg keys and reg values
/// </summary> /// </summary>
/// <returns>A Dictionary with reg keys as Dictionary keys and a Dictionary of (valuename, valuedata)</returns> /// <returns>A Dictionary with reg keys as Dictionary keys and a Dictionary of (valuename, valuedata)</returns>
private Dictionary<string, Dictionary<string, string>> ParseFile() private Dictionary<string, Dictionary<string, string>> ParseFile()
@@ -141,7 +141,7 @@ public class RegFileObject
} }
/// <summary> /// <summary>
/// Creates a flat Dictionary using given searcn pattern /// Creates a flat Dictionary using given searcn pattern
/// </summary> /// </summary>
/// <param name="content">The content string to be parsed</param> /// <param name="content">The content string to be parsed</param>
/// <returns>A Dictionary with retrieved keys and remaining content</returns> /// <returns>A Dictionary with retrieved keys and remaining content</returns>
@@ -202,7 +202,7 @@ public class RegFileObject
} }
/// <summary> /// <summary>
/// Creates a flat Dictionary using given searcn pattern /// Creates a flat Dictionary using given searcn pattern
/// </summary> /// </summary>
/// <param name="content">The content string to be parsed</param> /// <param name="content">The content string to be parsed</param>
/// <returns>A Dictionary with retrieved keys and remaining content</returns> /// <returns>A Dictionary with retrieved keys and remaining content</returns>
@@ -254,7 +254,7 @@ public class RegFileObject
} }
/// <summary> /// <summary>
/// Removes the leading and ending characters from the given string /// Removes the leading and ending characters from the given string
/// </summary> /// </summary>
/// <param name="sLine">given string</param> /// <param name="sLine">given string</param>
/// <returns>edited string</returns> /// <returns>edited string</returns>
@@ -268,7 +268,7 @@ public class RegFileObject
} }
/// <summary> /// <summary>
/// Removes the leading and ending parenthesis from the given string /// Removes the leading and ending parenthesis from the given string
/// </summary> /// </summary>
/// <param name="sLine">given string</param> /// <param name="sLine">given string</param>
/// <returns>edited string</returns> /// <returns>edited string</returns>
@@ -294,7 +294,7 @@ public class RegValueObject
private string value; private string value;
/// <summary> /// <summary>
/// Parameterless constructor /// Parameterless constructor
/// </summary> /// </summary>
public RegValueObject() public RegValueObject()
{ {
@@ -307,7 +307,7 @@ public class RegValueObject
} }
/// <summary> /// <summary>
/// Overloaded constructor /// Overloaded constructor
/// </summary> /// </summary>
/// <param name="propertyString">A line from the [Registry] section of the *.sig signature file</param> /// <param name="propertyString">A line from the [Registry] section of the *.sig signature file</param>
public RegValueObject(string regKeyName, string regValueName, string regValueData, string encoding) public RegValueObject(string regKeyName, string regValueName, string regValueData, string encoding)
@@ -326,7 +326,7 @@ public class RegValueObject
#region Public Methods #region Public Methods
/// <summary> /// <summary>
/// Overriden Method /// Overriden Method
/// </summary> /// </summary>
/// <returns>An entry for the [Registry] section of the *.sig signature file</returns> /// <returns>An entry for the [Registry] section of the *.sig signature file</returns>
public override string ToString() public override string ToString()
@@ -339,7 +339,7 @@ public class RegValueObject
#region Public Properties #region Public Properties
/// <summary> /// <summary>
/// Regsitry value name /// Regsitry value name
/// </summary> /// </summary>
[XmlElement("entry", typeof(string))] [XmlElement("entry", typeof(string))]
public string Entry public string Entry
@@ -349,7 +349,7 @@ public class RegValueObject
} }
/// <summary> /// <summary>
/// Registry value parent key /// Registry value parent key
/// </summary> /// </summary>
[XmlElement("key", typeof(string))] [XmlElement("key", typeof(string))]
public string ParentKey public string ParentKey
@@ -364,7 +364,7 @@ public class RegValueObject
} }
/// <summary> /// <summary>
/// Registry value root hive /// Registry value root hive
/// </summary> /// </summary>
[XmlElement("root", typeof(string))] [XmlElement("root", typeof(string))]
public string Root public string Root
@@ -374,7 +374,7 @@ public class RegValueObject
} }
/// <summary> /// <summary>
/// Registry value type /// Registry value type
/// </summary> /// </summary>
[XmlElement("type", typeof(string))] [XmlElement("type", typeof(string))]
public string Type public string Type
@@ -384,7 +384,7 @@ public class RegValueObject
} }
/// <summary> /// <summary>
/// Registry value data /// Registry value data
/// </summary> /// </summary>
[XmlElement("value", typeof(string))] [XmlElement("value", typeof(string))]
public string Value public string Value
@@ -447,7 +447,7 @@ public class RegValueObject
} }
/// <summary> /// <summary>
/// Retrieves the reg value type, parsing the prefix of the value /// Retrieves the reg value type, parsing the prefix of the value
/// </summary> /// </summary>
/// <param name="sTextLine">Registry value row string</param> /// <param name="sTextLine">Registry value row string</param>
/// <returns>Value</returns> /// <returns>Value</returns>
@@ -546,7 +546,7 @@ public class RegValueObject
} }
/// <summary> /// <summary>
/// Removes the leading and ending characters from the given string /// Removes the leading and ending characters from the given string
/// </summary> /// </summary>
/// <param name="sline">given string</param> /// <param name="sline">given string</param>
/// <returns>edited string</returns> /// <returns>edited string</returns>
@@ -560,7 +560,7 @@ public class RegValueObject
} }
/// <summary> /// <summary>
/// Removes the leading and ending parenthesis from the given string /// Removes the leading and ending parenthesis from the given string
/// </summary> /// </summary>
/// <param name="sline">given string</param> /// <param name="sline">given string</param>
/// <returns>edited string</returns> /// <returns>edited string</returns>
@@ -573,7 +573,7 @@ public class RegValueObject
} }
/// <summary> /// <summary>
/// Removes the ending backslashes from the given string /// Removes the ending backslashes from the given string
/// </summary> /// </summary>
/// <param name="sline">given string</param> /// <param name="sline">given string</param>
/// <returns>edited string</returns> /// <returns>edited string</returns>
@@ -585,7 +585,7 @@ public class RegValueObject
} }
/// <summary> /// <summary>
/// Converts the byte arrays (saved as array of string) into string /// Converts the byte arrays (saved as array of string) into string
/// </summary> /// </summary>
/// <param name="stringArray">Array of string</param> /// <param name="stringArray">Array of string</param>
/// <returns>String value</returns> /// <returns>String value</returns>

View File

@@ -37,16 +37,72 @@ namespace QuickLook;
public partial class App : Application public partial class App : Application
{ {
public static readonly string LocalDataPath = SettingHelper.LocalDataPath; public static readonly string LocalDataPath = GetSafeLocalDataPath();
public static readonly string UserPluginPath = Path.Combine(SettingHelper.LocalDataPath, @"QuickLook.Plugin\"); public static readonly string UserPluginPath = Path.Combine(LocalDataPath, @"QuickLook.Plugin\");
public static readonly string AppFullPath = Assembly.GetExecutingAssembly().Location; public static readonly string AppFullPath = Assembly.GetExecutingAssembly().Location ?? string.Empty;
public static readonly string AppPath = Path.GetDirectoryName(AppFullPath); public static readonly string AppPath = GetSafeAppPath();
public static readonly bool Is64Bit = Environment.Is64BitProcess; public static readonly bool Is64Bit = Environment.Is64BitProcess;
public static readonly bool IsUWP = ProcessHelper.IsRunningAsUWP(); public static readonly bool IsUWP = ProcessHelper.IsRunningAsUWP();
public static readonly bool IsWin11 = Environment.OSVersion.Version >= new Version(10, 0, 21996); public static readonly bool IsWin11 = Environment.OSVersion.Version >= new Version(10, 0, 21996);
public static readonly bool IsWin10 = !IsWin11 && Environment.OSVersion.Version >= new Version(10, 0); public static readonly bool IsWin10 = !IsWin11 && Environment.OSVersion.Version >= new Version(10, 0);
public static readonly bool IsGPUInBlacklist = SystemHelper.IsGPUInBlacklist(); public static readonly bool IsGPUInBlacklist = SystemHelper.IsGPUInBlacklist();
public static readonly bool IsPortable = SettingHelper.IsPortableVersion(); public static readonly bool IsPortable = SafeIsPortableVersion();
private static string GetSafeLocalDataPath()
{
try
{
return SettingHelper.LocalDataPath;
}
catch (ArgumentException)
{
// Fallback: determine data path based on portable mode detection
var isPortable = SafeIsPortableVersion();
if (isPortable)
{
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
var assemblyDir = !string.IsNullOrEmpty(assemblyLocation)
? Path.GetDirectoryName(assemblyLocation)
: AppDomain.CurrentDomain.BaseDirectory;
return Path.Combine(assemblyDir ?? string.Empty, @"UserData\");
}
else
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
@"pooi.moe\QuickLook\");
}
}
}
private static bool SafeIsPortableVersion()
{
try
{
return SettingHelper.IsPortableVersion();
}
catch (ArgumentException)
{
// Fallback: check for portable.lock file in current directory or base directory
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
var assemblyDir = !string.IsNullOrEmpty(assemblyLocation)
? Path.GetDirectoryName(assemblyLocation)
: AppDomain.CurrentDomain.BaseDirectory;
var lck = Path.Combine(assemblyDir ?? string.Empty, "portable.lock");
return File.Exists(lck);
}
}
private static string GetSafeAppPath()
{
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
if (!string.IsNullOrEmpty(assemblyLocation))
{
return Path.GetDirectoryName(assemblyLocation) ?? string.Empty;
}
return AppDomain.CurrentDomain.BaseDirectory;
}
private bool _cleanExit = true; private bool _cleanExit = true;
private Mutex _isRunning; private Mutex _isRunning;

View File

@@ -81,8 +81,7 @@ public class BackgroundVisualHost : FrameworkElement
private readonly CreateContentFunction _createContent; private readonly CreateContentFunction _createContent;
private readonly Action _invalidateMeasure; private readonly Action _invalidateMeasure;
private readonly AutoResetEvent _sync = private readonly AutoResetEvent _sync = new(false);
new AutoResetEvent(false);
public ThreadedVisualHelper( public ThreadedVisualHelper(
CreateContentFunction createContent, CreateContentFunction createContent,
@@ -125,17 +124,11 @@ public class BackgroundVisualHost : FrameworkElement
} }
} }
#region Private Fields
public ThreadedVisualHelper ThreadedHelper; public ThreadedVisualHelper ThreadedHelper;
private HostVisual _hostVisual; private HostVisual _hostVisual;
#endregion Private Fields
#region IsContentShowingProperty
/// <summary> /// <summary>
/// Identifies the IsContentShowing dependency property. /// Identifies the IsContentShowing dependency property.
/// </summary> /// </summary>
public static readonly DependencyProperty IsContentShowingProperty = DependencyProperty.Register( public static readonly DependencyProperty IsContentShowingProperty = DependencyProperty.Register(
"IsContentShowing", "IsContentShowing",
@@ -144,7 +137,7 @@ public class BackgroundVisualHost : FrameworkElement
new FrameworkPropertyMetadata(false, OnIsContentShowingChanged)); new FrameworkPropertyMetadata(false, OnIsContentShowingChanged));
/// <summary> /// <summary>
/// Gets or sets if the content is being displayed. /// Gets or sets if the content is being displayed.
/// </summary> /// </summary>
public bool IsContentShowing public bool IsContentShowing
{ {
@@ -163,12 +156,8 @@ public class BackgroundVisualHost : FrameworkElement
bvh.HideContentHelper(); bvh.HideContentHelper();
} }
#endregion IsContentShowingProperty
#region CreateContent Property
/// <summary> /// <summary>
/// Identifies the CreateContent dependency property. /// Identifies the CreateContent dependency property.
/// </summary> /// </summary>
public static readonly DependencyProperty CreateContentProperty = DependencyProperty.Register( public static readonly DependencyProperty CreateContentProperty = DependencyProperty.Register(
"CreateContent", "CreateContent",
@@ -177,7 +166,7 @@ public class BackgroundVisualHost : FrameworkElement
new FrameworkPropertyMetadata(OnCreateContentChanged)); new FrameworkPropertyMetadata(OnCreateContentChanged));
/// <summary> /// <summary>
/// Gets or sets the function used to create the visual to display in a background thread. /// Gets or sets the function used to create the visual to display in a background thread.
/// </summary> /// </summary>
public CreateContentFunction CreateContent public CreateContentFunction CreateContent
{ {
@@ -196,6 +185,4 @@ public class BackgroundVisualHost : FrameworkElement
bvh.CreateContentHelper(); bvh.CreateContentHelper();
} }
} }
#endregion CreateContent Property
} }

View File

@@ -135,7 +135,7 @@ public class BusyDecorator : Decorator, IDisposable
#region IsBusyIndicatorShowing Property #region IsBusyIndicatorShowing Property
/// <summary> /// <summary>
/// Identifies the IsBusyIndicatorShowing dependency property. /// Identifies the IsBusyIndicatorShowing dependency property.
/// </summary> /// </summary>
public static readonly DependencyProperty IsBusyIndicatorShowingProperty = DependencyProperty.Register( public static readonly DependencyProperty IsBusyIndicatorShowingProperty = DependencyProperty.Register(
"IsBusyIndicatorShowing", "IsBusyIndicatorShowing",
@@ -146,7 +146,7 @@ public class BusyDecorator : Decorator, IDisposable
OnIsBusyIndicatorShowingChanged)); OnIsBusyIndicatorShowingChanged));
/// <summary> /// <summary>
/// Gets or sets if the BusyIndicator is being shown. /// Gets or sets if the BusyIndicator is being shown.
/// </summary> /// </summary>
public bool IsBusyIndicatorShowing public bool IsBusyIndicatorShowing
{ {
@@ -178,7 +178,7 @@ public class BusyDecorator : Decorator, IDisposable
#region BusyStyle #region BusyStyle
/// <summary> /// <summary>
/// Identifies the <see cref="BusyStyle" /> property. /// Identifies the <see cref="BusyStyle" /> property.
/// </summary> /// </summary>
public static readonly DependencyProperty BusyStyleProperty = public static readonly DependencyProperty BusyStyleProperty =
DependencyProperty.Register( DependencyProperty.Register(
@@ -188,7 +188,7 @@ public class BusyDecorator : Decorator, IDisposable
new FrameworkPropertyMetadata(OnBusyStyleChanged)); new FrameworkPropertyMetadata(OnBusyStyleChanged));
/// <summary> /// <summary>
/// Gets or sets the Style to apply to the Control that is displayed as the busy indication. /// Gets or sets the Style to apply to the Control that is displayed as the busy indication.
/// </summary> /// </summary>
public Style BusyStyle public Style BusyStyle
{ {
@@ -208,7 +208,7 @@ public class BusyDecorator : Decorator, IDisposable
#region BusyHorizontalAlignment #region BusyHorizontalAlignment
/// <summary> /// <summary>
/// Identifies the <see cref="BusyHorizontalAlignment" /> property. /// Identifies the <see cref="BusyHorizontalAlignment" /> property.
/// </summary> /// </summary>
public static readonly DependencyProperty BusyHorizontalAlignmentProperty = DependencyProperty.Register( public static readonly DependencyProperty BusyHorizontalAlignmentProperty = DependencyProperty.Register(
"BusyHorizontalAlignment", "BusyHorizontalAlignment",
@@ -217,7 +217,7 @@ public class BusyDecorator : Decorator, IDisposable
new FrameworkPropertyMetadata(HorizontalAlignment.Center)); new FrameworkPropertyMetadata(HorizontalAlignment.Center));
/// <summary> /// <summary>
/// Gets or sets the HorizontalAlignment to use to layout the control that contains the busy indicator control. /// Gets or sets the HorizontalAlignment to use to layout the control that contains the busy indicator control.
/// </summary> /// </summary>
public HorizontalAlignment BusyHorizontalAlignment public HorizontalAlignment BusyHorizontalAlignment
{ {
@@ -230,7 +230,7 @@ public class BusyDecorator : Decorator, IDisposable
#region BusyVerticalAlignment #region BusyVerticalAlignment
/// <summary> /// <summary>
/// Identifies the <see cref="BusyVerticalAlignment" /> property. /// Identifies the <see cref="BusyVerticalAlignment" /> property.
/// </summary> /// </summary>
public static readonly DependencyProperty BusyVerticalAlignmentProperty = DependencyProperty.Register( public static readonly DependencyProperty BusyVerticalAlignmentProperty = DependencyProperty.Register(
"BusyVerticalAlignment", "BusyVerticalAlignment",
@@ -239,7 +239,7 @@ public class BusyDecorator : Decorator, IDisposable
new FrameworkPropertyMetadata(VerticalAlignment.Center)); new FrameworkPropertyMetadata(VerticalAlignment.Center));
/// <summary> /// <summary>
/// Gets or sets the the VerticalAlignment to use to layout the control that contains the busy indicator. /// Gets or sets the the VerticalAlignment to use to layout the control that contains the busy indicator.
/// </summary> /// </summary>
public VerticalAlignment BusyVerticalAlignment public VerticalAlignment BusyVerticalAlignment
{ {

View File

@@ -24,17 +24,17 @@ using System.Windows.Media.Animation;
namespace QuickLook.Controls.BusyDecorator; namespace QuickLook.Controls.BusyDecorator;
/// <summary> /// <summary>
/// Control extensions /// Control extensions
/// </summary> /// </summary>
internal static class ControlExtensions internal static class ControlExtensions
{ {
/// <summary> /// <summary>
/// The key used for storing the spinner Storyboard. /// The key used for storing the spinner Storyboard.
/// </summary> /// </summary>
private static readonly string SpinnerStoryBoardName = $"{typeof(FrameworkElement).Name}Spinner"; private static readonly string SpinnerStoryBoardName = $"{typeof(FrameworkElement).Name}Spinner";
/// <summary> /// <summary>
/// Start the spinning animation /// Start the spinning animation
/// </summary> /// </summary>
/// <typeparam name="T">FrameworkElement and ISpinable</typeparam> /// <typeparam name="T">FrameworkElement and ISpinable</typeparam>
/// <param name="control">Control to apply the rotation </param> /// <param name="control">Control to apply the rotation </param>
@@ -78,7 +78,7 @@ internal static class ControlExtensions
} }
/// <summary> /// <summary>
/// Stop the spinning animation /// Stop the spinning animation
/// </summary> /// </summary>
/// <typeparam name="T">FrameworkElement and ISpinable</typeparam> /// <typeparam name="T">FrameworkElement and ISpinable</typeparam>
/// <param name="control">Control to stop the rotation.</param> /// <param name="control">Control to stop the rotation.</param>

View File

@@ -18,17 +18,17 @@
namespace QuickLook.Controls.BusyDecorator; namespace QuickLook.Controls.BusyDecorator;
/// <summary> /// <summary>
/// Represents a spinable control /// Represents a spinable control
/// </summary> /// </summary>
internal interface ISpinable internal interface ISpinable
{ {
/// <summary> /// <summary>
/// Gets or sets the current spin (angle) animation of the icon. /// Gets or sets the current spin (angle) animation of the icon.
/// </summary> /// </summary>
public bool Spin { get; set; } public bool Spin { get; set; }
/// <summary> /// <summary>
/// Gets or sets the duration of the spinning animation (in seconds). This will stop and start the spin animation. /// Gets or sets the duration of the spinning animation (in seconds). This will stop and start the spin animation.
/// </summary> /// </summary>
public double SpinDuration { get; set; } public double SpinDuration { get; set; }
} }

View File

@@ -25,7 +25,7 @@ internal class SpinIcon : TextBlock, ISpinable
#region public bool Spin #region public bool Spin
/// <summary> /// <summary>
/// Identifies the Spin dependency property. /// Identifies the Spin dependency property.
/// </summary> /// </summary>
public static DependencyProperty SpinProperty = public static DependencyProperty SpinProperty =
DependencyProperty.Register("Spin", typeof(bool), typeof(SpinIcon), DependencyProperty.Register("Spin", typeof(bool), typeof(SpinIcon),
@@ -44,7 +44,7 @@ internal class SpinIcon : TextBlock, ISpinable
} }
/// <summary> /// <summary>
/// Gets or sets the current spin (angle) animation of the icon. /// Gets or sets the current spin (angle) animation of the icon.
/// </summary> /// </summary>
public bool Spin public bool Spin
{ {
@@ -58,7 +58,7 @@ internal class SpinIcon : TextBlock, ISpinable
#region public double SpinDuration #region public double SpinDuration
/// <summary> /// <summary>
/// Identifies the SpinDuration dependency property. /// Identifies the SpinDuration dependency property.
/// </summary> /// </summary>
public static DependencyProperty SpinDurationProperty = public static DependencyProperty SpinDurationProperty =
DependencyProperty.Register("SpinDuration", typeof(double), typeof(SpinIcon), DependencyProperty.Register("SpinDuration", typeof(double), typeof(SpinIcon),
@@ -76,7 +76,7 @@ internal class SpinIcon : TextBlock, ISpinable
} }
/// <summary> /// <summary>
/// Gets or sets the duration of the spinning animation (in seconds). This will stop and start the spin animation. /// Gets or sets the duration of the spinning animation (in seconds). This will stop and start the spin animation.
/// </summary> /// </summary>
public double SpinDuration public double SpinDuration
{ {

View File

@@ -43,7 +43,7 @@ public partial class GlassLayer : UserControl
#region public Visual BlurredElement #region public Visual BlurredElement
/// <summary> /// <summary>
/// Identifies the BlurredElement dependency property. /// Identifies the BlurredElement dependency property.
/// </summary> /// </summary>
public static DependencyProperty BlurredElementProperty = public static DependencyProperty BlurredElementProperty =
DependencyProperty.Register("BlurredElement", typeof(Visual), typeof(GlassLayer), null); DependencyProperty.Register("BlurredElement", typeof(Visual), typeof(GlassLayer), null);
@@ -62,7 +62,7 @@ public partial class GlassLayer : UserControl
#region public SolidColorBrush OverlayColor #region public SolidColorBrush OverlayColor
/// <summary> /// <summary>
/// Identifies the OverlayColor dependency property. /// Identifies the OverlayColor dependency property.
/// </summary> /// </summary>
public static DependencyProperty OverlayColorProperty = public static DependencyProperty OverlayColorProperty =
DependencyProperty.Register("OverlayColor", typeof(SolidColorBrush), typeof(GlassLayer), DependencyProperty.Register("OverlayColor", typeof(SolidColorBrush), typeof(GlassLayer),
@@ -82,7 +82,7 @@ public partial class GlassLayer : UserControl
#region public Visibility ColorOverlayVisibility #region public Visibility ColorOverlayVisibility
/// <summary> /// <summary>
/// Identifies the ColorOverlayVisibilityProperty dependency property. /// Identifies the ColorOverlayVisibilityProperty dependency property.
/// </summary> /// </summary>
public static DependencyProperty ColorOverlayVisibilityProperty = public static DependencyProperty ColorOverlayVisibilityProperty =
DependencyProperty.Register("ColorOverlayVisibility", typeof(Visibility), typeof(GlassLayer), DependencyProperty.Register("ColorOverlayVisibility", typeof(Visibility), typeof(GlassLayer),
@@ -100,7 +100,7 @@ public partial class GlassLayer : UserControl
#region public Visibility NoiseVisibility #region public Visibility NoiseVisibility
/// <summary> /// <summary>
/// Identifies the NoiseVisibility dependency property. /// Identifies the NoiseVisibility dependency property.
/// </summary> /// </summary>
public static DependencyProperty NoiseVisibilityProperty = public static DependencyProperty NoiseVisibilityProperty =
DependencyProperty.Register("NoiseVisibility", typeof(Visibility), typeof(GlassLayer), DependencyProperty.Register("NoiseVisibility", typeof(Visibility), typeof(GlassLayer),
@@ -120,7 +120,7 @@ public partial class GlassLayer : UserControl
#region public Visibility GlassVisibility #region public Visibility GlassVisibility
/// <summary> /// <summary>
/// Identifies the GlassVisibility dependency property. /// Identifies the GlassVisibility dependency property.
/// </summary> /// </summary>
public static DependencyProperty GlassVisibilityProperty = public static DependencyProperty GlassVisibilityProperty =
DependencyProperty.Register("GlassVisibility", typeof(Visibility), typeof(GlassLayer), DependencyProperty.Register("GlassVisibility", typeof(Visibility), typeof(GlassLayer),

View File

@@ -33,8 +33,8 @@ internal enum SLGP_FLAGS
SLGP_UNCPRIORITY = 0x2, SLGP_UNCPRIORITY = 0x2,
/// <summary> /// <summary>
/// Retrieves the raw path name. A raw path is something that might not exist and may include environment /// Retrieves the raw path name. A raw path is something that might not exist and may include environment
/// variables that need to be expanded /// variables that need to be expanded
/// </summary> /// </summary>
SLGP_RAWPATH = 0x4 SLGP_RAWPATH = 0x4
} }
@@ -62,13 +62,13 @@ internal struct WIN32_FIND_DATAW
internal enum SLR_FLAGS internal enum SLR_FLAGS
{ {
/// <summary> /// <summary>
/// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set, /// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set,
/// the high-order word of fFlags can be set to a time-out value that specifies the /// the high-order word of fFlags can be set to a time-out value that specifies the
/// maximum amount of time to be spent resolving the link. The function returns if the /// maximum amount of time to be spent resolving the link. The function returns if the
/// link cannot be resolved within the time-out duration. If the high-order word is set /// link cannot be resolved within the time-out duration. If the high-order word is set
/// to zero, the time-out duration will be set to the default value of 3,000 milliseconds /// to zero, the time-out duration will be set to the default value of 3,000 milliseconds
/// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out /// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out
/// duration, in milliseconds. /// duration, in milliseconds.
/// </summary> /// </summary>
SLR_NO_UI = 0x1, SLR_NO_UI = 0x1,
@@ -76,9 +76,9 @@ internal enum SLR_FLAGS
SLR_ANY_MATCH = 0x2, SLR_ANY_MATCH = 0x2,
/// <summary> /// <summary>
/// If the link object has changed, update its path and list of identifiers. /// If the link object has changed, update its path and list of identifiers.
/// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine /// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine
/// whether or not the link object has changed. /// whether or not the link object has changed.
/// </summary> /// </summary>
SLR_UPDATE = 0x4, SLR_UPDATE = 0x4,
@@ -92,10 +92,10 @@ internal enum SLR_FLAGS
SLR_NOTRACK = 0x20, SLR_NOTRACK = 0x20,
/// <summary> /// <summary>
/// Disable distributed link tracking. By default, distributed link tracking tracks /// Disable distributed link tracking. By default, distributed link tracking tracks
/// removable media across multiple devices based on the volume name. It also uses the /// removable media across multiple devices based on the volume name. It also uses the
/// Universal Naming Convention (UNC) path to track remote file systems whose drive letter /// Universal Naming Convention (UNC) path to track remote file systems whose drive letter
/// has changed. Setting SLR_NOLINKINFO disables both types of tracking. /// has changed. Setting SLR_NOLINKINFO disables both types of tracking.
/// </summary> /// </summary>
SLR_NOLINKINFO = 0x40, SLR_NOLINKINFO = 0x40,

View File

@@ -58,114 +58,64 @@ public partial class InfoPanel : UserControl
Dispatcher.BeginInvoke(new Action(() => image.Source = source)); Dispatcher.BeginInvoke(new Action(() => image.Source = source));
}); });
string name; var name = Path.GetFileName(path);
try
{
name = Path.GetFileName(path);
}
catch (ArgumentException)
{
// Handle invalid path characters gracefully
name = path;
}
catch (PathTooLongException)
{
// Handle path too long scenarios
name = path;
}
filename.Text = string.IsNullOrEmpty(name) ? path : name; filename.Text = string.IsNullOrEmpty(name) ? path : name;
try var last = File.GetLastWriteTime(path);
{ modDate.Text = string.Format(TranslationHelper.Get("InfoPanel_LastModified"),
var last = File.GetLastWriteTime(path); last.ToString(CultureInfo.CurrentCulture));
modDate.Text = string.Format(TranslationHelper.Get("InfoPanel_LastModified"),
last.ToString(CultureInfo.CurrentCulture));
}
catch (ArgumentException)
{
// Handle invalid path characters gracefully
modDate.Text = TranslationHelper.Get("InfoPanel_LastModified_Unavailable") ?? "Last modified: Unavailable";
}
catch (UnauthorizedAccessException)
{
// Handle access denied scenarios
modDate.Text = TranslationHelper.Get("InfoPanel_LastModified_Unavailable") ?? "Last modified: Unavailable";
}
catch (PathTooLongException)
{
// Handle path too long scenarios
modDate.Text = TranslationHelper.Get("InfoPanel_LastModified_Unavailable") ?? "Last modified: Unavailable";
}
Stop = false; Stop = false;
_ = Task.Run(() => _ = Task.Run(() =>
{ {
try if (File.Exists(path))
{ {
if (File.Exists(path)) var size = new FileInfo(path).Length;
{
var size = new FileInfo(path).Length;
Dispatcher.Invoke(() => { totalSize.Text = size.ToPrettySize(2); }); Dispatcher.Invoke(() => { totalSize.Text = size.ToPrettySize(2); });
} }
else if (Path.GetPathRoot(path) == path) // is this a drive? else if (Path.GetPathRoot(path) == path) // is this a drive?
{ {
FileHelper.GetDriveSpace(path, out var totalSpace, out var totalFreeSpace); FileHelper.GetDriveSpace(path, out var totalSpace, out var totalFreeSpace);
Dispatcher.Invoke(() =>
{
totalSize.Text =
string.Format(TranslationHelper.Get("InfoPanel_DriveSize"),
totalSpace.ToPrettySize(2),
totalFreeSpace.ToPrettySize(2));
});
}
else if (Directory.Exists(path))
{
FileHelper.CountFolder(path, ref _stop,
out var totalDirsL, out var totalFilesL, out var totalSizeL);
if (!Stop)
Dispatcher.Invoke(() => Dispatcher.Invoke(() =>
{ {
string t;
var folders = totalDirsL == 0
? string.Empty
: string.Format(TranslationHelper.Get(
totalDirsL == 1 ? "InfoPanel_Folder" : "InfoPanel_Folders"), totalDirsL);
var files = totalFilesL == 0
? string.Empty
: string.Format(TranslationHelper.Get(
totalFilesL == 1 ? "InfoPanel_File" : "InfoPanel_Files"), totalFilesL);
if (!string.IsNullOrEmpty(folders) && !string.IsNullOrEmpty(files))
t = string.Format(
TranslationHelper.Get("InfoPanel_FolderAndFile"), folders, files);
else if (string.IsNullOrEmpty(folders) && string.IsNullOrEmpty(files))
t = string.Empty;
else
t = $"({folders}{files})";
totalSize.Text = totalSize.Text =
string.Format(TranslationHelper.Get("InfoPanel_DriveSize"), $"{totalSizeL.ToPrettySize(2)} {t}";
totalSpace.ToPrettySize(2),
totalFreeSpace.ToPrettySize(2));
}); });
}
else if (Directory.Exists(path))
{
FileHelper.CountFolder(path, ref _stop,
out var totalDirsL, out var totalFilesL, out var totalSizeL);
if (!Stop)
Dispatcher.Invoke(() =>
{
string t;
var folders = totalDirsL == 0
? string.Empty
: string.Format(TranslationHelper.Get(
totalDirsL == 1 ? "InfoPanel_Folder" : "InfoPanel_Folders"), totalDirsL);
var files = totalFilesL == 0
? string.Empty
: string.Format(TranslationHelper.Get(
totalFilesL == 1 ? "InfoPanel_File" : "InfoPanel_Files"), totalFilesL);
if (!string.IsNullOrEmpty(folders) && !string.IsNullOrEmpty(files))
t = string.Format(
TranslationHelper.Get("InfoPanel_FolderAndFile"), folders, files);
else if (string.IsNullOrEmpty(folders) && string.IsNullOrEmpty(files))
t = string.Empty;
else
t = $"({folders}{files})";
totalSize.Text =
$"{totalSizeL.ToPrettySize(2)} {t}";
});
}
}
catch (ArgumentException)
{
// Handle invalid path characters gracefully
Dispatcher.Invoke(() => { totalSize.Text = "Size: Unavailable"; });
}
catch (UnauthorizedAccessException)
{
// Handle access denied scenarios
Dispatcher.Invoke(() => { totalSize.Text = "Size: Unavailable"; });
}
catch (PathTooLongException)
{
// Handle path too long scenarios
Dispatcher.Invoke(() => { totalSize.Text = "Size: Unavailable"; });
} }
}); });
} }