mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-06 16:04:38 +01:00
Rework mod import UX
This commit is contained in:
parent
bbc090085b
commit
34234927d8
6 changed files with 179 additions and 15 deletions
2
Luna
2
Luna
|
|
@ -1 +1 @@
|
|||
Subproject commit 384b437a8cf16b4b1a51da43a4837d8fcc2116bd
|
||||
Subproject commit 14544263ad78d95d96235eab597a7cb0a76015eb
|
||||
|
|
@ -19,6 +19,7 @@ public partial class TexToolsImporter : IDisposable
|
|||
private readonly string _tmpFile;
|
||||
|
||||
private readonly IEnumerable<FileInfo> _modPackFiles;
|
||||
private readonly int _previousModPackCount;
|
||||
private readonly int _modPackCount;
|
||||
private FileStream? _tmpFileStream;
|
||||
private StreamDisposer? _streamDisposer;
|
||||
|
|
@ -37,8 +38,16 @@ public partial class TexToolsImporter : IDisposable
|
|||
|
||||
public TexToolsImporter(int count, IEnumerable<FileInfo> modPackFiles, Action<FileInfo, DirectoryInfo?, Exception?> handler,
|
||||
Configuration config, DuplicateManager duplicates, ModNormalizer modNormalizer, ModManager modManager, FileCompactor compactor,
|
||||
MigrationManager migrationManager)
|
||||
MigrationManager migrationManager, TexToolsImporter? previous)
|
||||
{
|
||||
if (previous is not null)
|
||||
{
|
||||
if (previous.State is not ImporterState.Done)
|
||||
throw new ArgumentException($"The previous {nameof(TexToolsImporter)} must have completed its job.");
|
||||
|
||||
_previousModPackCount = previous.ExtractedMods.Count;
|
||||
}
|
||||
|
||||
_baseDirectory = modManager.BasePath;
|
||||
_tmpFile = Path.Combine(_baseDirectory.FullName, TempFileName);
|
||||
_modPackFiles = modPackFiles;
|
||||
|
|
@ -48,14 +57,16 @@ public partial class TexToolsImporter : IDisposable
|
|||
_modManager = modManager;
|
||||
_compactor = compactor;
|
||||
_migrationManager = migrationManager;
|
||||
_modPackCount = count;
|
||||
ExtractedMods = new List<(FileInfo, DirectoryInfo?, Exception?)>(count);
|
||||
_modPackCount = count + _previousModPackCount;
|
||||
ExtractedMods = new List<(FileInfo, DirectoryInfo?, Exception?)>(count + _previousModPackCount);
|
||||
_token = _cancellation.Token;
|
||||
if (previous is not null)
|
||||
ExtractedMods.AddRange(previous.ExtractedMods);
|
||||
Task.Run(ImportFiles, _token)
|
||||
.ContinueWith(_ => CloseStreams(), TaskScheduler.Default)
|
||||
.ContinueWith(_ =>
|
||||
{
|
||||
foreach (var (file, dir, error) in ExtractedMods)
|
||||
foreach (var (file, dir, error) in ExtractedMods.Skip(_previousModPackCount))
|
||||
handler(file, dir, error);
|
||||
}, TaskScheduler.Default);
|
||||
}
|
||||
|
|
@ -83,7 +94,7 @@ public partial class TexToolsImporter : IDisposable
|
|||
private void ImportFiles()
|
||||
{
|
||||
State = ImporterState.None;
|
||||
_currentModPackIdx = 0;
|
||||
_currentModPackIdx = _previousModPackCount;
|
||||
foreach (var file in _modPackFiles)
|
||||
{
|
||||
_currentModDirectory = null;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,24 @@ public partial class TexToolsImporter
|
|||
private string _currentOptionName = string.Empty;
|
||||
private string _currentFileName = string.Empty;
|
||||
|
||||
public (string Text, float Progress, bool Ended, bool Successful) ComputeNotificationData()
|
||||
{
|
||||
if (_modPackCount is 0)
|
||||
return ("Nothing to extract.", 1.0f, true, true);
|
||||
|
||||
if (_modPackCount == _currentModPackIdx)
|
||||
{
|
||||
var success = ExtractedMods.Count(t => t.Error == null);
|
||||
|
||||
return ($"Successfully extracted {success} / {ExtractedMods.Count} files.", 1.0f, true, success == ExtractedMods.Count);
|
||||
}
|
||||
|
||||
if (State is ImporterState.DeduplicatingFiles)
|
||||
return ($"Deduplicating {_currentModName}...", 1.0f, false, true);
|
||||
|
||||
return ($"Extracting {_currentModName}...", _currentNumFiles > 0 ? _currentFileIdx / (float)_currentNumFiles : 0.0f, false, true);
|
||||
}
|
||||
|
||||
public bool DrawProgressInfo(Vector2 size)
|
||||
{
|
||||
if (_modPackCount is 0)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using Dalamud.Interface.ImGuiNotification;
|
||||
using Luna;
|
||||
using Penumbra.Import;
|
||||
using Penumbra.Import.Structs;
|
||||
using Penumbra.Mods.Editor;
|
||||
using Penumbra.Services;
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ public class ModImportManager(
|
|||
|
||||
public void TryUnpacking()
|
||||
{
|
||||
if (Importing || !_modsToUnpack.TryDequeue(out var newMods))
|
||||
if (Importing && _import!.State is not ImporterState.Done || !_modsToUnpack.TryDequeue(out var newMods))
|
||||
return;
|
||||
|
||||
var files = newMods.Where(s =>
|
||||
|
|
@ -49,7 +50,7 @@ public class ModImportManager(
|
|||
return;
|
||||
|
||||
_import = new TexToolsImporter(files.Length, files, AddNewMod, config, duplicates, modNormalizer, modManager, compactor,
|
||||
migrationManager);
|
||||
migrationManager, _import);
|
||||
}
|
||||
|
||||
public bool Importing
|
||||
|
|
|
|||
|
|
@ -1,22 +1,37 @@
|
|||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Interface.ImGuiNotification;
|
||||
using Dalamud.Interface.ImGuiNotification.EventArgs;
|
||||
using ImSharp;
|
||||
using Luna;
|
||||
using Penumbra.Import.Structs;
|
||||
using Penumbra.Mods.Manager;
|
||||
using MessageService = Penumbra.Services.MessageService;
|
||||
|
||||
namespace Penumbra.UI;
|
||||
|
||||
/// <summary> Draw the progress information for import. </summary>
|
||||
public sealed class ImportPopup : Window
|
||||
public sealed class ImportPopup : Window, INotificationAwareMessage
|
||||
{
|
||||
public const string WindowLabel = "Penumbra Import Status";
|
||||
|
||||
private readonly ModImportManager _modImportManager;
|
||||
private readonly MessageService _messageService;
|
||||
private static readonly Vector2 OneHalf = Vector2.One / 2;
|
||||
|
||||
private IActiveNotification? _notification;
|
||||
private string _notificationMessage = string.Empty;
|
||||
private float _notificationProgress = 1.0f;
|
||||
private bool _notificationEnded = true;
|
||||
private bool _notificationSuccessful = true;
|
||||
private bool _openPopup = false;
|
||||
|
||||
public bool HasNotification
|
||||
=> _notification is not null;
|
||||
|
||||
public bool WasDrawn { get; private set; }
|
||||
public bool PopupWasDrawn { get; private set; }
|
||||
|
||||
public ImportPopup(ModImportManager modImportManager)
|
||||
public ImportPopup(ModImportManager modImportManager, MessageService messageService)
|
||||
: base(WindowLabel,
|
||||
WindowFlags.NoCollapse
|
||||
| WindowFlags.NoDecoration
|
||||
|
|
@ -30,6 +45,7 @@ public sealed class ImportPopup : Window
|
|||
| WindowFlags.NoTitleBar, true)
|
||||
{
|
||||
_modImportManager = modImportManager;
|
||||
_messageService = messageService;
|
||||
DisableWindowSounds = true;
|
||||
IsOpen = true;
|
||||
RespectCloseHotkey = false;
|
||||
|
|
@ -58,8 +74,26 @@ public sealed class ImportPopup : Window
|
|||
if (!_modImportManager.IsImporting(out var import))
|
||||
return;
|
||||
|
||||
if (!Im.Popup.IsOpen("##PenumbraImportPopup"u8))
|
||||
(_notificationMessage, _notificationProgress, _notificationEnded, _notificationSuccessful) = import.ComputeNotificationData();
|
||||
|
||||
_notification?.Title = NotificationTitle;
|
||||
_notification?.Type = NotificationType;
|
||||
_notification?.Content = _notificationMessage;
|
||||
_notification?.Progress = _notificationProgress;
|
||||
_notification?.UserDismissable = _notificationEnded;
|
||||
|
||||
if (_openPopup)
|
||||
{
|
||||
Im.Popup.Open("##PenumbraImportPopup"u8);
|
||||
_openPopup = false;
|
||||
}
|
||||
|
||||
if (!Im.Popup.IsOpen("##PenumbraImportPopup"u8))
|
||||
{
|
||||
if (_notification is null)
|
||||
_messageService.AddMessage(this, false, true, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var display = Im.Io.DisplaySize;
|
||||
var height = Math.Max(display.Y / 4, 15 * Im.Style.FrameHeightWithSpacing);
|
||||
|
|
@ -78,10 +112,109 @@ public sealed class ImportPopup : Window
|
|||
terminate = true;
|
||||
}
|
||||
|
||||
if (import.State != ImporterState.Done)
|
||||
{
|
||||
if (Im.Button("Continue in the Background"u8,
|
||||
new Vector2((Im.ContentRegion.Available.X - Im.GetStyle().ItemSpacing.X) * 0.5f, 0.0f)))
|
||||
Im.Popup.CloseCurrent();
|
||||
Im.Line.Same();
|
||||
}
|
||||
|
||||
terminate |= import.State == ImporterState.Done
|
||||
? Im.Button("Close"u8, -Vector2.UnitX)
|
||||
: import.DrawCancelButton(-Vector2.UnitX);
|
||||
if (terminate)
|
||||
_modImportManager.ClearImport();
|
||||
}
|
||||
|
||||
#region Luna Message implementation
|
||||
|
||||
private NotificationType NotificationType
|
||||
=> (_notificationEnded, _notificationSuccessful) switch
|
||||
{
|
||||
(false, _) => NotificationType.Info,
|
||||
(true, true) => NotificationType.Success,
|
||||
(true, false) => NotificationType.Error,
|
||||
};
|
||||
|
||||
private string NotificationTitle
|
||||
=> (_notificationEnded, _notificationSuccessful) switch
|
||||
{
|
||||
(false, _) => "Importing mods",
|
||||
(true, true) => "Successfully imported mods",
|
||||
(true, false) => "Failed to import some mods",
|
||||
};
|
||||
|
||||
NotificationType IMessage.NotificationType
|
||||
=> NotificationType;
|
||||
|
||||
string IMessage.NotificationMessage
|
||||
=> _notificationMessage;
|
||||
|
||||
TimeSpan IMessage.NotificationDuration
|
||||
=> TimeSpan.MaxValue;
|
||||
|
||||
string IMessage.NotificationTitle
|
||||
=> NotificationTitle;
|
||||
|
||||
string IMessage.LogMessage
|
||||
=> string.Empty;
|
||||
|
||||
SeString IMessage.ChatMessage
|
||||
=> SeString.Empty;
|
||||
|
||||
StringU8 IMessage.StoredMessage
|
||||
=> StringU8.Empty;
|
||||
|
||||
StringU8 IMessage.StoredTooltip
|
||||
=> StringU8.Empty;
|
||||
|
||||
void IMessage.OnNotificationActions(INotificationDrawArgs args)
|
||||
{
|
||||
if (_notificationEnded)
|
||||
{
|
||||
if (Im.Button("Open Report"u8, -Vector2.UnitX))
|
||||
{
|
||||
_openPopup = true;
|
||||
_notification?.DismissNow();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Im.Button("Show Details"u8, new Vector2((Im.ContentRegion.Available.X - Im.GetStyle().ItemSpacing.X) * 0.5f, 0.0f)))
|
||||
{
|
||||
_openPopup = true;
|
||||
_notification?.DismissNow();
|
||||
}
|
||||
|
||||
Im.Line.Same();
|
||||
if (_modImportManager.IsImporting(out var import) && import.DrawCancelButton(-Vector2.UnitX))
|
||||
{
|
||||
_modImportManager.ClearImport();
|
||||
_notification?.DismissNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void INotificationAwareMessage.OnNotificationCreated(IActiveNotification notification)
|
||||
{
|
||||
var previousNotification = _notification;
|
||||
_notification = notification;
|
||||
previousNotification?.DismissNow();
|
||||
notification.Progress = _notificationProgress;
|
||||
notification.UserDismissable = _notificationEnded;
|
||||
notification.Dismiss += OnNotificationDismissed;
|
||||
}
|
||||
|
||||
private void OnNotificationDismissed(INotificationDismissArgs args)
|
||||
{
|
||||
if (args.Notification != _notification)
|
||||
return;
|
||||
|
||||
_notification = null;
|
||||
if (!_openPopup && !PopupWasDrawn)
|
||||
_modImportManager.ClearImport();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -350,10 +350,11 @@ public sealed class DebugTab : Window, ITab<TabType>
|
|||
if (table)
|
||||
{
|
||||
var importing = _modImporter.IsImporting(out var importer);
|
||||
table.DrawDataPair("Is Importing"u8, importing.ToString());
|
||||
table.DrawDataPair("Importer State"u8, (importer?.State ?? ImporterState.None).ToString());
|
||||
table.DrawDataPair("Import Window Was Drawn"u8, _importPopup.WasDrawn.ToString());
|
||||
table.DrawDataPair("Import Popup Was Drawn"u8, _importPopup.PopupWasDrawn.ToString());
|
||||
table.DrawDataPair("Is Importing"u8, importing.ToString());
|
||||
table.DrawDataPair("Importer State"u8, (importer?.State ?? ImporterState.None).ToString());
|
||||
table.DrawDataPair("Import Notification Exists"u8, _importPopup.HasNotification.ToString());
|
||||
table.DrawDataPair("Import Window Was Drawn"u8, _importPopup.WasDrawn.ToString());
|
||||
table.DrawDataPair("Import Popup Was Drawn"u8, _importPopup.PopupWasDrawn.ToString());
|
||||
table.DrawColumn("Import Batches"u8);
|
||||
table.NextColumn();
|
||||
foreach (var (index, batch) in _modImporter.ModBatches.Index())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue