mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-02-21 23:37:44 +01:00
Show logs on loading dialog
This commit is contained in:
parent
9db4e2f3a1
commit
877906ae15
4 changed files with 81 additions and 28 deletions
|
|
@ -1,4 +1,5 @@
|
|||
using System.ComponentModel;
|
||||
using System.Collections.Concurrent;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
|
@ -14,6 +15,7 @@ using Dalamud.Plugin.Internal;
|
|||
using Dalamud.Utility;
|
||||
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
|
|
@ -31,7 +33,7 @@ namespace Dalamud;
|
|||
Justification = "Multiple fixed blocks")]
|
||||
internal sealed unsafe class LoadingDialog
|
||||
{
|
||||
private static int wasGloballyHidden;
|
||||
private readonly RollingList<string> logs = new(20);
|
||||
|
||||
private Thread? thread;
|
||||
private HWND hwndTaskDialog;
|
||||
|
|
@ -60,6 +62,13 @@ internal sealed unsafe class LoadingDialog
|
|||
AutoUpdatePlugins,
|
||||
}
|
||||
|
||||
/// <summary>Gets the queue where log entries that are not processed yet are stored.</summary>
|
||||
public static ConcurrentQueue<(string Line, LogEvent LogEvent)> NewLogEntries { get; } = new();
|
||||
|
||||
/// <summary>Gets a value indicating whether the initial Dalamud loading dialog will not show again until next
|
||||
/// game restart.</summary>
|
||||
public static bool IsGloballyHidden { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current state of the dialog.
|
||||
/// </summary>
|
||||
|
|
@ -98,7 +107,7 @@ internal sealed unsafe class LoadingDialog
|
|||
/// </summary>
|
||||
public void Show()
|
||||
{
|
||||
if (Volatile.Read(ref wasGloballyHidden) == 1)
|
||||
if (IsGloballyHidden)
|
||||
return;
|
||||
|
||||
if (this.thread?.IsAlive == true)
|
||||
|
|
@ -119,6 +128,7 @@ internal sealed unsafe class LoadingDialog
|
|||
/// </summary>
|
||||
public void HideAndJoin()
|
||||
{
|
||||
IsGloballyHidden = true;
|
||||
if (this.thread?.IsAlive is not true)
|
||||
return;
|
||||
|
||||
|
|
@ -210,6 +220,42 @@ internal sealed unsafe class LoadingDialog
|
|||
}
|
||||
}
|
||||
|
||||
private void UpdateExpandedInformation()
|
||||
{
|
||||
const int maxCharactersPerLine = 80;
|
||||
|
||||
if (NewLogEntries.IsEmpty)
|
||||
return;
|
||||
while (NewLogEntries.TryDequeue(out var e))
|
||||
{
|
||||
var t = e.Line.AsSpan();
|
||||
while (!t.IsEmpty)
|
||||
{
|
||||
var i = t.IndexOfAny('\r', '\n');
|
||||
var line = i == -1 ? t : t[..i];
|
||||
t = i == -1 ? ReadOnlySpan<char>.Empty : t[(i + 1)..];
|
||||
if (line.IsEmpty)
|
||||
continue;
|
||||
|
||||
this.logs.Add(
|
||||
line.Length < maxCharactersPerLine ? line.ToString() : $"{line[..(maxCharactersPerLine - 3)]}...");
|
||||
}
|
||||
}
|
||||
|
||||
var sb = new StringBuilder();
|
||||
foreach (var l in this.logs)
|
||||
sb.AppendLine(l);
|
||||
|
||||
fixed (void* pszText = sb.ToString())
|
||||
{
|
||||
SendMessageW(
|
||||
this.hwndTaskDialog,
|
||||
(uint)TASKDIALOG_MESSAGES.TDM_SET_ELEMENT_TEXT,
|
||||
(WPARAM)(int)TASKDIALOG_ELEMENTS.TDE_EXPANDED_INFORMATION,
|
||||
(LPARAM)pszText);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateButtonEnabled()
|
||||
{
|
||||
if (this.hwndTaskDialog == default)
|
||||
|
|
@ -227,6 +273,7 @@ internal sealed unsafe class LoadingDialog
|
|||
|
||||
this.UpdateMainInstructionText();
|
||||
this.UpdateContentText();
|
||||
this.UpdateExpandedInformation();
|
||||
this.UpdateButtonEnabled();
|
||||
SendMessageW(hwnd, (int)TASKDIALOG_MESSAGES.TDM_SET_PROGRESS_BAR_MARQUEE, 1, 0);
|
||||
|
||||
|
|
@ -245,6 +292,7 @@ internal sealed unsafe class LoadingDialog
|
|||
|
||||
case TASKDIALOG_NOTIFICATIONS.TDN_TIMER:
|
||||
this.UpdateContentText();
|
||||
this.UpdateExpandedInformation();
|
||||
return S.S_OK;
|
||||
}
|
||||
|
||||
|
|
@ -260,10 +308,13 @@ internal sealed unsafe class LoadingDialog
|
|||
? null
|
||||
: Icon.ExtractAssociatedIcon(Path.Combine(workingDirectory, "Dalamud.Injector.exe"));
|
||||
|
||||
fixed (void* pszEmpty = "-")
|
||||
fixed (void* pszWindowTitle = "Dalamud")
|
||||
fixed (void* pszHide = Loc.Localize("LoadingDialogHide", "Hide"))
|
||||
fixed (void* pszThemesManifestResourceName = "RT_MANIFEST_THEMES")
|
||||
fixed (void* pszDalamudBoot = "Dalamud.Boot.dll")
|
||||
fixed (void* pszThemesManifestResourceName = "RT_MANIFEST_THEMES")
|
||||
fixed (void* pszHide = Loc.Localize("LoadingDialogHide", "Hide"))
|
||||
fixed (void* pszShowLatestLogs = Loc.Localize("LoadingDialogShowLatestLogs", "Show Latest Logs"))
|
||||
fixed (void* pszHideLatestLogs = Loc.Localize("LoadingDialogHideLatestLogs", "Hide Latest Logs"))
|
||||
{
|
||||
var taskDialogButton = new TASKDIALOG_BUTTON
|
||||
{
|
||||
|
|
@ -277,6 +328,7 @@ internal sealed unsafe class LoadingDialog
|
|||
hInstance = (HINSTANCE)Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().ManifestModule),
|
||||
dwFlags = (int)TDF_CAN_BE_MINIMIZED |
|
||||
(int)TDF_SHOW_MARQUEE_PROGRESS_BAR |
|
||||
(int)TDF_EXPAND_FOOTER_AREA |
|
||||
(int)TDF_CALLBACK_TIMER |
|
||||
(extractedIcon is null ? 0 : (int)TDF_USE_HICON_MAIN),
|
||||
dwCommonButtons = 0,
|
||||
|
|
@ -291,14 +343,14 @@ internal sealed unsafe class LoadingDialog
|
|||
pRadioButtons = null,
|
||||
nDefaultRadioButton = 0,
|
||||
pszVerificationText = null,
|
||||
pszExpandedInformation = null,
|
||||
pszExpandedControlText = null,
|
||||
pszCollapsedControlText = null,
|
||||
pszExpandedInformation = (ushort*)pszEmpty,
|
||||
pszExpandedControlText = (ushort*)pszShowLatestLogs,
|
||||
pszCollapsedControlText = (ushort*)pszHideLatestLogs,
|
||||
pszFooterIcon = null,
|
||||
pszFooter = null,
|
||||
pfCallback = &HResultFuncBinder,
|
||||
lpCallbackData = 0,
|
||||
cxWidth = 0,
|
||||
cxWidth = 360,
|
||||
};
|
||||
|
||||
HANDLE hActCtx = default;
|
||||
|
|
@ -338,7 +390,7 @@ internal sealed unsafe class LoadingDialog
|
|||
}
|
||||
}
|
||||
|
||||
Interlocked.Exchange(ref wasGloballyHidden, 1);
|
||||
IsGloballyHidden = true;
|
||||
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -250,19 +250,20 @@ internal static class ServiceManager
|
|||
try
|
||||
{
|
||||
// Wait for all blocking constructors to complete first.
|
||||
await WaitWithTimeoutConsent(blockingEarlyLoadingServices.Select(x => getAsyncTaskMap[x]),
|
||||
await WaitWithTimeoutConsent(
|
||||
blockingEarlyLoadingServices.Select(x => getAsyncTaskMap[x]),
|
||||
LoadingDialog.State.LoadingDalamud);
|
||||
|
||||
// All the BlockingEarlyLoadedService constructors have been run,
|
||||
// and blockerTasks now will not change. Now wait for them.
|
||||
// Note that ServiceManager.CallWhenServicesReady does not get to register a blocker.
|
||||
await WaitWithTimeoutConsent(blockerTasks,
|
||||
await WaitWithTimeoutConsent(
|
||||
blockerTasks,
|
||||
LoadingDialog.State.LoadingPlugins);
|
||||
|
||||
Log.Verbose("=============== BLOCKINGSERVICES & TASKS INITIALIZED ===============");
|
||||
Timings.Event("BlockingServices Initialized");
|
||||
BlockingServicesLoadedTaskCompletionSource.SetResult();
|
||||
loadingDialog.HideAndJoin();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -277,6 +278,10 @@ internal static class ServiceManager
|
|||
|
||||
Log.Error(e, "Failed resolving blocking services");
|
||||
}
|
||||
finally
|
||||
{
|
||||
loadingDialog.HideAndJoin();
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue