Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b118532
Version bump
Iridium-IO Aug 26, 2026
ea38b4b
Transition to TOML
Iridium-IO Aug 29, 2026
9ef33d7
Add online pulling of language updates.
Iridium-IO Aug 29, 2026
9bd6cf0
move update handlignt o lazy translate
Iridium-IO Aug 29, 2026
bfd2c15
Reload language even if we can't download anything (allows translator…
Iridium-IO Aug 29, 2026
ac08b08
Fix race condition when accessing the database while updating / readi…
Iridium-IO Aug 30, 2026
2402879
Use language nuget package instead of direct project reference
Iridium-IO Aug 29, 2026
9268236
Add some memory leak fixes to folder lifecycle
Iridium-IO Aug 30, 2026
c39b1fe
Improve RAM utilisation by removing unecessary FileInfo objects in An…
Iridium-IO Aug 31, 2026
34cb613
Merge pull request #653 from IridiumIO/LanguageTOML
Iridium-IO Aug 31, 2026
020abe3
Improve memory handling of BackgroundCompactor and sprinkle a bunch o…
Iridium-IO Sep 1, 2026
689f5d0
Create basic SteamMonitor tab
Iridium-IO Jun 13, 2025
1b64f4d
Merge Steam Monitor Page
Iridium-IO Sep 1, 2026
7857845
Migrate SteamFolderViewModel to use MVVM.VBSourceGenerators propertie…
Iridium-IO Sep 1, 2026
750c9ab
Add cancellation support to steam games page
Iridium-IO Sep 1, 2026
575f64a
Opening databsse view from steammonitor page now searches for the act…
Iridium-IO Sep 1, 2026
f2eb6ae
Add badges to compression state
Iridium-IO Sep 1, 2026
50074c2
Get Steam Header image for steam list view (TODO: consolidate with th…
Iridium-IO Sep 1, 2026
a44c012
Should have done this from the start - use steam's own installed cach…
Iridium-IO Sep 1, 2026
b3b1132
Added overview of "saved" and "can be saved" sums to Steam Games page.
Iridium-IO Sep 1, 2026
2e9d271
Version bump
Iridium-IO Sep 1, 2026
d022d49
Update localisation points for new Steam Library page
Iridium-IO Sep 1, 2026
b2821ad
Added more missing translation strings
Iridium-IO Sep 1, 2026
f7aec7a
Keep external drive folders alive in Watcher - Fixes #625
Iridium-IO Sep 1, 2026
144cf79
Add DirectStorage warning to Steam Library page
Iridium-IO Sep 1, 2026
c13a4bc
Fix stupid issue where the Watcher would never be able to resume if a…
Iridium-IO Sep 1, 2026
34ebba9
Fix Watcher not actually being able to switch from Idle > Scheduled m…
Iridium-IO Sep 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CompactGUI.Core/Analyser.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -116,7 +116,7 @@ private static bool GetContainsCompressedFiles(List<AnalysedFileDetails> fileCom
? WOFCompressionAlgorithm.NO_COMPRESSION
: WOFHelper.DetectCompression(fileInfo);

return new AnalysedFileDetails { FileName = file, CompressedSize = compressedSize, UncompressedSize = uncompressedSize, CompressionMode = compressionMode, FileInfo = fileInfo };
return new AnalysedFileDetails { FileName = file, CompressedSize = compressedSize, UncompressedSize = uncompressedSize, CompressionMode = compressionMode};
}
catch (IOException ex)
{
Expand DownExpand Up@@ -151,7 +151,7 @@ public List<ExtensionResult> GetPoorlyCompressedExtensions()
public void Dispose()
{
_folderMonitor.Dispose();
_analysedFileDetails?.Clear();
_analysedFileDetails = null;
}
}

Expand Down
2 changes: 1 addition & 1 deletion CompactGUI.Core/Settings/Settings.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,7 +46,7 @@ public partial class Settings : ObservableRecipient
[ObservableProperty] private WindowState windowState = WindowState.Normal;
[ObservableProperty] private bool alwaysShowDetailedCompressionMode = false;

[ObservableProperty] private string language = "en-US";
[ObservableProperty] private string language = "en-AU";

partial void OnScheduledBackgroundIntervalChanged(int value) => UpdateNextScheduledBackgroundRun();

Expand Down
1 change: 0 additions & 1 deletion CompactGUI.Core/SharedObjects.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,6 @@ public sealed class AnalysedFileDetails
public long UncompressedSize { get; set; }
public long CompressedSize { get; set; }
public WOFCompressionAlgorithm CompressionMode { get; set; }
public FileInfo? FileInfo { get; set; }
}


Expand Down
150 changes: 95 additions & 55 deletions CompactGUI.Watcher/BackgroundCompactor.vb
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,7 @@ Public Class BackgroundCompactor
Private isCompactingPaused As Boolean = False ' Track if compacting is paused

Private _compactor As Core.Compactor
Private _compactorAnalyser As Core.Analyser

Private _excludedFileTypes As String()

Expand All@@ -48,104 +49,143 @@ Public Class BackgroundCompactor

Dim effectiveExclusions = If(excludedFileTypes Is Nothing, _excludedFileTypes, excludedFileTypes)

_compactor = New Core.Compactor(folder, compressionLevel, effectiveExclusions, New Core.Analyser(folder, NullLogger(Of Core.Analyser).Instance))
_compactorAnalyser = New Core.Analyser(folder, NullLogger(Of Core.Analyser).Instance)
_compactor = New Core.Compactor(folder, compressionLevel, effectiveExclusions, _compactorAnalyser)
If isCompactingPaused Then _compactor.Pause()

Return _compactor.RunAsync(Nothing)

End Function

Public Async Function StartCompactingAsync(folders As IEnumerable(Of WatchedFolder)) As Task(Of Boolean)
WatcherLog.BackgroundCompactingStarted(_logger)

cancellationTokenSource = New CancellationTokenSource()

IsCompactorActive = True
Dim currentProcess = Process.GetCurrentProcess()
Dim originalPriority = currentProcess.PriorityClass

Dim currentProcess As Process = Process.GetCurrentProcess()
currentProcess.PriorityClass = ProcessPriorityClass.Idle
Try
IsCompactorActive = True
isCompacting = True
currentProcess.PriorityClass = ProcessPriorityClass.Idle

isCompacting = True
For Each folder In folders.ToList()
If cancellationTokenSource.IsCancellationRequested Then Return False
If Not Await CompactFolderAsync(folder, folders) Then Return False

For Each folder In folders.ToList
folder.IsWorking = True
WatcherLog.FinishedCompactingFolder(_logger, folder.DisplayName)
Next

WatcherLog.CompactingFolder(_logger, folder.DisplayName)
Dim folderSkipList = If(folder.SkipList Is Nothing, Array.Empty(Of String), folder.SkipList.ToArray())
Dim compactingTask = BeginCompacting(folder.Folder, folder.CompressionLevel, folderSkipList)
WatcherLog.BackgroundCompactingFinished(_logger)
Return True
Finally
IsCompactorActive = False
isCompacting = False
isCompactingPaused = False

cancellationTokenSource.Dispose()
cancellationTokenSource = Nothing

If cancellationTokenSource.IsCancellationRequested Then
Trace.WriteLine("Compacting cancelled by user.")
folder.IsWorking = False
IsCompactorActive = False
isCompacting = False ' Ensure compacting status is reset after operation
_compactor.Dispose()
Return False
End If
currentProcess.PriorityClass = originalPriority
currentProcess.Dispose()
End Try
End Function

Dim result = Await compactingTask
If result AndAlso folders.Contains(folder) Then
' Ensure the folder is still in the original collection before updating
Private Async Function CompactFolderAsync(folder As WatchedFolder, folders As IEnumerable(Of WatchedFolder)) As Task(Of Boolean)
folder.IsWorking = True

Dim analyser As New Core.Analyser(folder.Folder, NullLogger(Of Core.Analyser).Instance)
Try
WatcherLog.CompactingFolder(_logger, folder.DisplayName)

Dim analysed = Await analyser.GetAnalysedFilesAsync(Nothing)
Dim folderSkipList = If(folder.SkipList Is Nothing, Array.Empty(Of String)(), folder.SkipList.ToArray())
Dim compactingTask = BeginCompacting(folder.Folder, folder.CompressionLevel, folderSkipList)

folder.LastCheckedDate = DateTime.Now
folder.LastCheckedSize = analyser.CompressedBytes
folder.LastCompressedSize = analyser.CompressedBytes
folder.LastSystemModifiedDate = DateTime.Now
Dim mainCompressionLVL = analysed.Select(Function(f) f.CompressionMode).Max
folder.CompressionLevel = mainCompressionLVL
If cancellationTokenSource.IsCancellationRequested Then _compactor?.Cancel()

folder.LastCompressedDate = DateTime.Now
Dim result = Await compactingTask

folder.HasTargetChanged = False
If cancellationTokenSource.IsCancellationRequested Then Return False

If result AndAlso folders.Contains(folder) Then
Await UpdateFolderStatisticsAsync(folder)
End If

Return True
Finally
DisposeCurrentCompactor()
folder.IsWorking = False
folder.RefreshProperties()
_compactor.Dispose()
WatcherLog.FinishedCompactingFolder(_logger, folder.DisplayName)
Next
End Try
End Function

IsCompactorActive = False
isCompacting = False ' Ensure compacting status is reset after operation
WatcherLog.BackgroundCompactingFinished(_logger)
currentProcess.PriorityClass = ProcessPriorityClass.Normal
Return True
Private Async Function UpdateFolderStatisticsAsync(folder As WatchedFolder) As Task
Using analyser As New Core.Analyser(folder.Folder, NullLogger(Of Core.Analyser).Instance)
Dim analysed = Await analyser.GetAnalysedFilesAsync(CancellationToken.None)

folder.LastCheckedDate = DateTime.Now
folder.LastCheckedSize = analyser.CompressedBytes
folder.LastCompressedSize = analyser.CompressedBytes
folder.LastSystemModifiedDate = DateTime.Now

If analysed IsNot Nothing AndAlso analysed.Count > 0 Then
folder.CompressionLevel = analysed.Max(Function(file) file.CompressionMode)
End If

folder.LastCompressedDate = DateTime.Now
folder.HasTargetChanged = False
End Using
End Function

Private Sub FinishRun(runCancellation As CancellationTokenSource, currentProcess As Process, originalPriority As ProcessPriorityClass)
If ReferenceEquals(cancellationTokenSource, runCancellation) Then cancellationTokenSource = Nothing

runCancellation.Dispose()

IsCompactorActive = False
isCompacting = False
isCompactingPaused = False

Try
currentProcess.PriorityClass = originalPriority
Finally
currentProcess.Dispose()
End Try
End Sub

Public Sub PauseCompacting()
If Not isCompacting OrElse isCompactingPaused Then
Return
End If
If Not isCompacting OrElse isCompactingPaused Then Return

WatcherLog.PausingBackgroundCompactor(_logger)
isCompactingPaused = True ' Indicate compacting is paused
isCompactingPaused = True
_compactor?.Pause()
End Sub

Public Sub ResumeCompacting()
If Not isCompactingPaused OrElse Not isCompacting Then
Return
End If
If Not isCompactingPaused OrElse Not isCompacting Then Return

WatcherLog.ResumingBackgroundCompactor(_logger)
isCompactingPaused = False ' Indicate compacting is no longer paused
isCompactingPaused = False
_compactor?.Resume()
End Sub

Public Sub CancelCompacting()
If Not isCompacting Then
Return
End If
If Not isCompacting Then Return

Debug.WriteLine("Cancelling background compactor...")
cancellationTokenSource.Cancel()
cancellationTokenSource.Dispose()

cancellationTokenSource?.Cancel()
_compactor?.Cancel()
_compactor?.Dispose()
isCompacting = False
isCompactingPaused = False ' Reset pause state on cancellation
End Sub

Private Sub DisposeCurrentCompactor()
Dim compactor = _compactor
_compactor = Nothing
compactor?.Dispose()

Dim analyser = _compactorAnalyser
_compactorAnalyser = Nothing
analyser?.Dispose()
End Sub

End Class
9 changes: 6 additions & 3 deletions CompactGUI.Watcher/WatchedFolder.vb
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,6 +28,9 @@ Public Class WatchedFolder
<AttachAttribute(GetType(JsonIgnoreAttribute))>
<ObservableProperty> Private _IsEditing As Boolean = False

<AttachAttribute(GetType(JsonIgnoreAttribute))>
<ObservableProperty> Private _IsDriveUnavailable As Boolean = False

' --- Monitoring State ---
<AttachAttribute(GetType(JsonIgnoreAttribute))>
<ObservableProperty> Private _HasTargetChanged As Boolean = False
Expand DownExpand Up@@ -66,13 +69,13 @@ Public Class WatchedFolder
End Sub

Public Sub PauseMonitoring()
If FSWatcher IsNot Nothing Then
If FSWatcher IsNot Nothing AndAlso Not IsDriveUnavailable Then
FSWatcher.EnableRaisingEvents = False
End If
End Sub

Public Sub ResumeMonitoring()
If FSWatcher IsNot Nothing Then
If FSWatcher IsNot Nothing AndAlso Not IsDriveUnavailable Then
FSWatcher.EnableRaisingEvents = True
End If
End Sub
Expand DownExpand Up@@ -131,4 +134,4 @@ Public Class WatchedFolder
Dispose(disposing:=True)
GC.SuppressFinalize(Me)
End Sub
End Class
End Class
Loading
Loading