mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Add Option to notify instead of auto install.
And General Fixes
This commit is contained in:
parent
60aa23efcd
commit
f05cb52da2
4 changed files with 72 additions and 14 deletions
|
|
@ -78,6 +78,7 @@ public class Configuration : IPluginConfiguration, ISavable, IService
|
||||||
public bool HideMachinistOffhandFromChangedItems { get; set; } = true;
|
public bool HideMachinistOffhandFromChangedItems { get; set; } = true;
|
||||||
public bool DefaultTemporaryMode { get; set; } = false;
|
public bool DefaultTemporaryMode { get; set; } = false;
|
||||||
public bool EnableDirectoryWatch { get; set; } = false;
|
public bool EnableDirectoryWatch { get; set; } = false;
|
||||||
|
public bool EnableAutomaticModImport { get; set; } = false;
|
||||||
public bool EnableCustomShapes { get; set; } = true;
|
public bool EnableCustomShapes { get; set; } = true;
|
||||||
public PcpSettings PcpSettings = new();
|
public PcpSettings PcpSettings = new();
|
||||||
public RenameField ShowRename { get; set; } = RenameField.BothDataPrio;
|
public RenameField ShowRename { get; set; } = RenameField.BothDataPrio;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
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;
|
||||||
|
|
@ -11,16 +12,16 @@ public class FileWatcher : IDisposable, IService
|
||||||
private readonly Task _consumer;
|
private readonly Task _consumer;
|
||||||
private readonly ConcurrentDictionary<string, byte> _pending = new(StringComparer.OrdinalIgnoreCase);
|
private readonly ConcurrentDictionary<string, byte> _pending = new(StringComparer.OrdinalIgnoreCase);
|
||||||
private readonly ModImportManager _modImportManager;
|
private readonly ModImportManager _modImportManager;
|
||||||
|
private readonly MessageService _messageService;
|
||||||
private readonly Configuration _config;
|
private readonly Configuration _config;
|
||||||
private readonly bool _enabled;
|
|
||||||
|
|
||||||
public FileWatcher(ModImportManager modImportManager, Configuration config)
|
public FileWatcher(ModImportManager modImportManager, MessageService messageService, Configuration config)
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
_modImportManager = modImportManager;
|
_modImportManager = modImportManager;
|
||||||
_enabled = config.EnableDirectoryWatch;
|
_messageService = messageService;
|
||||||
|
_config = config;
|
||||||
|
|
||||||
if (!_enabled) return;
|
if (!_config.EnableDirectoryWatch) return;
|
||||||
|
|
||||||
_queue = Channel.CreateBounded<string>(new BoundedChannelOptions(256)
|
_queue = Channel.CreateBounded<string>(new BoundedChannelOptions(256)
|
||||||
{
|
{
|
||||||
|
|
@ -55,13 +56,13 @@ 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 (!_enabled || !_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 (!_enabled) 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))
|
||||||
{
|
{
|
||||||
|
|
@ -100,10 +101,29 @@ public class FileWatcher : IDisposable, IService
|
||||||
var fi = new FileInfo(path);
|
var fi = new FileInfo(path);
|
||||||
var len = fi.Length;
|
var len = fi.Length;
|
||||||
if (len > 0 && len == lastLen)
|
if (len > 0 && len == lastLen)
|
||||||
|
{
|
||||||
|
if (_config.EnableAutomaticModImport)
|
||||||
{
|
{
|
||||||
_modImportManager.AddUnpack(path);
|
_modImportManager.AddUnpack(path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var invoked = false;
|
||||||
|
Action<bool> installRequest = args =>
|
||||||
|
{
|
||||||
|
if (invoked) return;
|
||||||
|
invoked = true;
|
||||||
|
_modImportManager.AddUnpack(path);
|
||||||
|
};
|
||||||
|
|
||||||
|
_messageService.PrintModFoundInfo(
|
||||||
|
Path.GetFileNameWithoutExtension(path),
|
||||||
|
installRequest);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lastLen = len;
|
lastLen = len;
|
||||||
}
|
}
|
||||||
|
|
@ -116,7 +136,7 @@ public class FileWatcher : IDisposable, IService
|
||||||
|
|
||||||
public void UpdateDirectory(string newPath)
|
public void UpdateDirectory(string newPath)
|
||||||
{
|
{
|
||||||
if (!_enabled || _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;
|
||||||
|
|
@ -125,7 +145,7 @@ public class FileWatcher : IDisposable, IService
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (!_enabled) return;
|
if (!_config.EnableDirectoryWatch) return;
|
||||||
_fsw.EnableRaisingEvents = false;
|
_fsw.EnableRaisingEvents = false;
|
||||||
_cts.Cancel();
|
_cts.Cancel();
|
||||||
_fsw.Dispose();
|
_fsw.Dispose();
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,44 @@
|
||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
|
using Dalamud.Interface.ImGuiNotification.EventArgs;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Excel.Sheets;
|
||||||
using OtterGui.Log;
|
using OtterGui.Log;
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
|
using OtterGui.Text;
|
||||||
using Penumbra.GameData.Data;
|
using Penumbra.GameData.Data;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
using static OtterGui.Classes.MessageService;
|
||||||
using Notification = OtterGui.Classes.Notification;
|
using Notification = OtterGui.Classes.Notification;
|
||||||
|
|
||||||
namespace Penumbra.Services;
|
namespace Penumbra.Services;
|
||||||
|
|
||||||
|
public class InstallNotification(string message, Action<bool> installRequest) : IMessage
|
||||||
|
{
|
||||||
|
private readonly Action<bool> _installRequest = installRequest;
|
||||||
|
private bool _invoked = false;
|
||||||
|
|
||||||
|
public string Message { get; } = message;
|
||||||
|
|
||||||
|
public NotificationType NotificationType => NotificationType.Info;
|
||||||
|
|
||||||
|
public uint NotificationDuration => 10000;
|
||||||
|
|
||||||
|
public void OnNotificationActions(INotificationDrawArgs args)
|
||||||
|
{
|
||||||
|
if (ImUtf8.ButtonEx("Install"u8, "Install this mod."u8, disabled: _invoked))
|
||||||
|
{
|
||||||
|
_installRequest(true);
|
||||||
|
_invoked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class MessageService(Logger log, IUiBuilder builder, IChatGui chat, INotificationManager notificationManager)
|
public class MessageService(Logger log, IUiBuilder builder, IChatGui chat, INotificationManager notificationManager)
|
||||||
: OtterGui.Classes.MessageService(log, builder, chat, notificationManager), IService
|
: OtterGui.Classes.MessageService(log, builder, chat, notificationManager), IService
|
||||||
{
|
{
|
||||||
|
|
@ -55,4 +80,11 @@ public class MessageService(Logger log, IUiBuilder builder, IChatGui chat, INoti
|
||||||
$"Cowardly refusing to load replacement for {originalGamePath.Filename().ToString().ToLowerInvariant()} by {mod.Name}{(messageComplement.Length > 0 ? ":\n" : ".")}{messageComplement}",
|
$"Cowardly refusing to load replacement for {originalGamePath.Filename().ToString().ToLowerInvariant()} by {mod.Name}{(messageComplement.Length > 0 ? ":\n" : ".")}{messageComplement}",
|
||||||
NotificationType.Warning, 10000));
|
NotificationType.Warning, 10000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void PrintModFoundInfo(string fileName, Action<bool> installRequest)
|
||||||
|
{
|
||||||
|
AddMessage(
|
||||||
|
new InstallNotification($"A new mod has been found: {fileName}", installRequest)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ 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;
|
||||||
|
|
||||||
|
|
@ -69,7 +70,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,
|
MigrationSectionDrawer migrationDrawer, CollectionAutoSelector autoSelector, CleanupService cleanupService, MessageService messageService,
|
||||||
AttributeHook attributeHook, PcpService pcpService)
|
AttributeHook attributeHook, PcpService pcpService)
|
||||||
{
|
{
|
||||||
_pluginInterface = pluginInterface;
|
_pluginInterface = pluginInterface;
|
||||||
|
|
@ -96,6 +97,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
@ -649,9 +651,12 @@ public class SettingsTab : ITab, IUiService
|
||||||
DrawDefaultModImportFolder();
|
DrawDefaultModImportFolder();
|
||||||
DrawPcpFolder();
|
DrawPcpFolder();
|
||||||
DrawDefaultModExportPath();
|
DrawDefaultModExportPath();
|
||||||
Checkbox("Enable Automatic Import of Mods from Directory",
|
Checkbox("Enable Directory Watcher",
|
||||||
"Enables a File Watcher that automatically listens for Mod files that enter, causing Penumbra to automatically import these mods.",
|
"Enables a File Watcher that automatically listens for Mod files that enter, 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",
|
||||||
|
"Uses the File Watcher in order to not just open a Popup, but fully automatically import new mods.",
|
||||||
|
_config.EnableAutomaticModImport, v => _config.EnableAutomaticModImport = v);
|
||||||
DrawFileWatcherPath();
|
DrawFileWatcherPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue