Slight cleanup and autoformat.

This commit is contained in:
Ottermandias 2025-10-22 21:56:16 +02:00
parent c8cf560fc1
commit cbedc878b9
5 changed files with 66 additions and 40 deletions

View file

@ -43,7 +43,6 @@ public class Penumbra : IDalamudPlugin
private readonly TempModManager _tempMods; private readonly TempModManager _tempMods;
private readonly TempCollectionManager _tempCollections; private readonly TempCollectionManager _tempCollections;
private readonly ModManager _modManager; private readonly ModManager _modManager;
private readonly FileWatcher _fileWatcher;
private readonly CollectionManager _collectionManager; private readonly CollectionManager _collectionManager;
private readonly Configuration _config; private readonly Configuration _config;
private readonly CharacterUtility _characterUtility; private readonly CharacterUtility _characterUtility;
@ -81,7 +80,6 @@ public class Penumbra : IDalamudPlugin
_residentResources = _services.GetService<ResidentResourceManager>(); _residentResources = _services.GetService<ResidentResourceManager>();
_services.GetService<ResourceManagerService>(); // Initialize because not required anywhere else. _services.GetService<ResourceManagerService>(); // Initialize because not required anywhere else.
_modManager = _services.GetService<ModManager>(); _modManager = _services.GetService<ModManager>();
_fileWatcher = _services.GetService<FileWatcher>();
_collectionManager = _services.GetService<CollectionManager>(); _collectionManager = _services.GetService<CollectionManager>();
_tempCollections = _services.GetService<TempCollectionManager>(); _tempCollections = _services.GetService<TempCollectionManager>();
_redrawService = _services.GetService<RedrawService>(); _redrawService = _services.GetService<RedrawService>();

View file

@ -1,9 +1,9 @@
using System.Threading.Channels; using System.Threading.Channels;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.Services;
using Penumbra.Mods.Manager; using Penumbra.Mods.Manager;
namespace Penumbra.Services; namespace Penumbra.Services;
public class FileWatcher : IDisposable, IService public class FileWatcher : IDisposable, IService
{ {
private readonly FileSystemWatcher _fsw; private readonly FileSystemWatcher _fsw;
@ -21,20 +21,21 @@ public class FileWatcher : IDisposable, IService
_messageService = messageService; _messageService = messageService;
_config = config; _config = config;
if (!_config.EnableDirectoryWatch) return; if (!_config.EnableDirectoryWatch)
return;
_queue = Channel.CreateBounded<string>(new BoundedChannelOptions(256) _queue = Channel.CreateBounded<string>(new BoundedChannelOptions(256)
{ {
SingleReader = true, SingleReader = true,
SingleWriter = false, SingleWriter = false,
FullMode = BoundedChannelFullMode.DropOldest FullMode = BoundedChannelFullMode.DropOldest,
}); });
_fsw = new FileSystemWatcher(_config.WatchDirectory) _fsw = new FileSystemWatcher(_config.WatchDirectory)
{ {
IncludeSubdirectories = false, IncludeSubdirectories = false,
NotifyFilter = NotifyFilters.FileName | NotifyFilters.CreationTime, NotifyFilter = NotifyFilters.FileName | NotifyFilters.CreationTime,
InternalBufferSize = 32 * 1024 InternalBufferSize = 32 * 1024,
}; };
// Only wake us for the exact patterns we care about // Only wake us for the exact patterns we care about
@ -56,13 +57,17 @@ public class FileWatcher : IDisposable, IService
private void OnPath(object? sender, FileSystemEventArgs e) private void OnPath(object? sender, FileSystemEventArgs e)
{ {
// Cheap de-dupe: only queue once per filename until processed // Cheap de-dupe: only queue once per filename until processed
if (!_config.EnableDirectoryWatch || !_pending.TryAdd(e.FullPath, 0)) return; if (!_config.EnableDirectoryWatch || !_pending.TryAdd(e.FullPath, 0))
return;
_ = _queue.Writer.TryWrite(e.FullPath); _ = _queue.Writer.TryWrite(e.FullPath);
} }
private async Task ConsumerLoopAsync(CancellationToken token) private async Task ConsumerLoopAsync(CancellationToken token)
{ {
if (!_config.EnableDirectoryWatch) return; if (!_config.EnableDirectoryWatch)
return;
var reader = _queue.Reader; var reader = _queue.Reader;
while (await reader.WaitToReadAsync(token).ConfigureAwait(false)) while (await reader.WaitToReadAsync(token).ConfigureAwait(false))
{ {
@ -72,7 +77,10 @@ public class FileWatcher : IDisposable, IService
{ {
await ProcessOneAsync(path, token).ConfigureAwait(false); await ProcessOneAsync(path, token).ConfigureAwait(false);
} }
catch (OperationCanceledException) { Penumbra.Log.Debug($"[FileWatcher] Canceled via Token."); } catch (OperationCanceledException)
{
Penumbra.Log.Debug($"[FileWatcher] Canceled via Token.");
}
catch (Exception ex) catch (Exception ex)
{ {
Penumbra.Log.Debug($"[FileWatcher] Error during Processing: {ex}"); Penumbra.Log.Debug($"[FileWatcher] Error during Processing: {ex}");
@ -92,9 +100,13 @@ public class FileWatcher : IDisposable, IService
const int maxTries = 40; const int maxTries = 40;
long lastLen = -1; long lastLen = -1;
for (int i = 0; i < maxTries && !token.IsCancellationRequested; i++) for (var i = 0; i < maxTries && !token.IsCancellationRequested; i++)
{ {
if (!File.Exists(path)) { await Task.Delay(100, token); continue; } if (!File.Exists(path))
{
await Task.Delay(100, token);
continue;
}
try try
{ {
@ -112,7 +124,9 @@ public class FileWatcher : IDisposable, IService
var invoked = false; var invoked = false;
Action<bool> installRequest = args => Action<bool> installRequest = args =>
{ {
if (invoked) return; if (invoked)
return;
invoked = true; invoked = true;
_modImportManager.AddUnpack(path); _modImportManager.AddUnpack(path);
}; };
@ -127,8 +141,14 @@ public class FileWatcher : IDisposable, IService
lastLen = len; lastLen = len;
} }
catch (IOException) { Penumbra.Log.Debug($"[FileWatcher] File is still being written to."); } catch (IOException)
catch (UnauthorizedAccessException) { Penumbra.Log.Debug($"[FileWatcher] File is locked."); } {
Penumbra.Log.Debug($"[FileWatcher] File is still being written to.");
}
catch (UnauthorizedAccessException)
{
Penumbra.Log.Debug($"[FileWatcher] File is locked.");
}
await Task.Delay(150, token); await Task.Delay(150, token);
} }
@ -136,7 +156,8 @@ public class FileWatcher : IDisposable, IService
public void UpdateDirectory(string newPath) public void UpdateDirectory(string newPath)
{ {
if (!_config.EnableDirectoryWatch || _fsw is null || !Directory.Exists(newPath) || string.IsNullOrWhiteSpace(newPath)) return; if (!_config.EnableDirectoryWatch || _fsw is null || !Directory.Exists(newPath) || string.IsNullOrWhiteSpace(newPath))
return;
_fsw.EnableRaisingEvents = false; _fsw.EnableRaisingEvents = false;
_fsw.Path = newPath; _fsw.Path = newPath;
@ -145,12 +166,22 @@ public class FileWatcher : IDisposable, IService
public void Dispose() public void Dispose()
{ {
if (!_config.EnableDirectoryWatch) return; if (!_config.EnableDirectoryWatch)
return;
_fsw.EnableRaisingEvents = false; _fsw.EnableRaisingEvents = false;
_cts.Cancel(); _cts.Cancel();
_fsw.Dispose(); _fsw.Dispose();
_queue.Writer.TryComplete(); _queue.Writer.TryComplete();
try { _consumer.Wait(TimeSpan.FromSeconds(5)); } catch { /* swallow */ } try
{
_consumer.Wait(TimeSpan.FromSeconds(5));
}
catch
{
/* swallow */
}
_cts.Dispose(); _cts.Dispose();
} }
} }

View file

@ -20,7 +20,6 @@ namespace Penumbra.Services;
public class InstallNotification(string message, Action<bool> installRequest) : IMessage public class InstallNotification(string message, Action<bool> installRequest) : IMessage
{ {
private readonly Action<bool> _installRequest = installRequest;
private bool _invoked = false; private bool _invoked = false;
public string Message { get; } = message; public string Message { get; } = message;
@ -33,7 +32,7 @@ public class InstallNotification(string message, Action<bool> installRequest) :
{ {
if (ImUtf8.ButtonEx("Install"u8, "Install this mod."u8, disabled: _invoked)) if (ImUtf8.ButtonEx("Install"u8, "Install this mod."u8, disabled: _invoked))
{ {
_installRequest(true); installRequest(true);
_invoked = true; _invoked = true;
} }
} }

View file

@ -53,7 +53,6 @@ public class SettingsTab : ITab, IUiService
private readonly MigrationSectionDrawer _migrationDrawer; private readonly MigrationSectionDrawer _migrationDrawer;
private readonly CollectionAutoSelector _autoSelector; private readonly CollectionAutoSelector _autoSelector;
private readonly CleanupService _cleanupService; private readonly CleanupService _cleanupService;
private readonly MessageService _messageService;
private readonly AttributeHook _attributeHook; private readonly AttributeHook _attributeHook;
private readonly PcpService _pcpService; private readonly PcpService _pcpService;
@ -70,7 +69,7 @@ public class SettingsTab : ITab, IUiService
CharacterUtility characterUtility, ResidentResourceManager residentResources, ModExportManager modExportManager, FileWatcher fileWatcher, HttpApi httpApi, CharacterUtility characterUtility, ResidentResourceManager residentResources, ModExportManager modExportManager, FileWatcher fileWatcher, HttpApi httpApi,
DalamudSubstitutionProvider dalamudSubstitutionProvider, FileCompactor compactor, DalamudConfigService dalamudConfig, DalamudSubstitutionProvider dalamudSubstitutionProvider, FileCompactor compactor, DalamudConfigService dalamudConfig,
IDataManager gameData, PredefinedTagManager predefinedTagConfig, CrashHandlerService crashService, IDataManager gameData, PredefinedTagManager predefinedTagConfig, CrashHandlerService crashService,
MigrationSectionDrawer migrationDrawer, CollectionAutoSelector autoSelector, CleanupService cleanupService, MessageService messageService, MigrationSectionDrawer migrationDrawer, CollectionAutoSelector autoSelector, CleanupService cleanupService,
AttributeHook attributeHook, PcpService pcpService) AttributeHook attributeHook, PcpService pcpService)
{ {
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
@ -97,7 +96,6 @@ public class SettingsTab : ITab, IUiService
_migrationDrawer = migrationDrawer; _migrationDrawer = migrationDrawer;
_autoSelector = autoSelector; _autoSelector = autoSelector;
_cleanupService = cleanupService; _cleanupService = cleanupService;
_messageService = messageService;
_attributeHook = attributeHook; _attributeHook = attributeHook;
_pcpService = pcpService; _pcpService = pcpService;
} }
@ -652,10 +650,10 @@ public class SettingsTab : ITab, IUiService
DrawPcpFolder(); DrawPcpFolder();
DrawDefaultModExportPath(); DrawDefaultModExportPath();
Checkbox("Enable Directory Watcher", Checkbox("Enable Directory Watcher",
"Enables a File Watcher that automatically listens for Mod files that enter, causing Penumbra to open a Popup to import these mods.", "Enables a File Watcher that automatically listens for Mod files that enter a specified directory, causing Penumbra to open a popup to import these mods.",
_config.EnableDirectoryWatch, v => _config.EnableDirectoryWatch = v); _config.EnableDirectoryWatch, v => _config.EnableDirectoryWatch = v);
Checkbox("Enable Fully Automatic Import", Checkbox("Enable Fully Automatic Import",
"Uses the File Watcher in order to not just open a Popup, but fully automatically import new mods.", "Uses the File Watcher in order to skip the query popup and automatically import any new mods.",
_config.EnableAutomaticModImport, v => _config.EnableAutomaticModImport = v); _config.EnableAutomaticModImport, v => _config.EnableAutomaticModImport = v);
DrawFileWatcherPath(); DrawFileWatcherPath();
} }