fix offset for transfer bar at the bottom, use async collections, clear filter on tab change + add button to clear, require ctrl for align syncshells

This commit is contained in:
rootdarkarchon
2023-10-22 17:12:44 +02:00
parent 17d66ee0a6
commit a51ce22d28
5 changed files with 76 additions and 41 deletions

View File

@@ -22,6 +22,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
private readonly ICallGateSubscriber<string?, string?, object> _customizePlusOnScaleUpdate; private readonly ICallGateSubscriber<string?, string?, object> _customizePlusOnScaleUpdate;
private readonly ICallGateSubscriber<Character?, object> _customizePlusRevertCharacter; private readonly ICallGateSubscriber<Character?, object> _customizePlusRevertCharacter;
private readonly ICallGateSubscriber<string, Character?, object> _customizePlusSetBodyScaleToCharacter; private readonly ICallGateSubscriber<string, Character?, object> _customizePlusSetBodyScaleToCharacter;
private readonly DalamudPluginInterface _pi;
private readonly DalamudUtilService _dalamudUtil; private readonly DalamudUtilService _dalamudUtil;
private readonly ICallGateSubscriber<(int, int)> _glamourerApiVersions; private readonly ICallGateSubscriber<(int, int)> _glamourerApiVersions;
private readonly ICallGateSubscriber<string, GameObject?, uint, object>? _glamourerApplyAll; private readonly ICallGateSubscriber<string, GameObject?, uint, object>? _glamourerApplyAll;
@@ -47,7 +48,6 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
private readonly ICallGateSubscriber<Character, object> _palettePlusRemoveCharaPalette; private readonly ICallGateSubscriber<Character, object> _palettePlusRemoveCharaPalette;
private readonly ICallGateSubscriber<Character, string, object> _palettePlusSetCharaPalette; private readonly ICallGateSubscriber<Character, string, object> _palettePlusSetCharaPalette;
private readonly FuncSubscriber<string, string, Dictionary<string, string>, string, int, PenumbraApiEc> _penumbraAddTemporaryMod; private readonly FuncSubscriber<string, string, Dictionary<string, string>, string, int, PenumbraApiEc> _penumbraAddTemporaryMod;
private readonly FuncSubscriber<(int, int)> _penumbraApiVersion;
private readonly FuncSubscriber<string, int, bool, PenumbraApiEc> _penumbraAssignTemporaryCollection; private readonly FuncSubscriber<string, int, bool, PenumbraApiEc> _penumbraAssignTemporaryCollection;
private readonly FuncSubscriber<string, string, TextureType, bool, Task> _penumbraConvertTextureFile; private readonly FuncSubscriber<string, string, TextureType, bool, Task> _penumbraConvertTextureFile;
private readonly FuncSubscriber<string, PenumbraApiEc> _penumbraCreateNamedTemporaryCollection; private readonly FuncSubscriber<string, PenumbraApiEc> _penumbraCreateNamedTemporaryCollection;
@@ -64,7 +64,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
private readonly FuncSubscriber<string, PenumbraApiEc> _penumbraRemoveTemporaryCollection; private readonly FuncSubscriber<string, PenumbraApiEc> _penumbraRemoveTemporaryCollection;
private readonly FuncSubscriber<string, string, int, PenumbraApiEc> _penumbraRemoveTemporaryMod; private readonly FuncSubscriber<string, string, int, PenumbraApiEc> _penumbraRemoveTemporaryMod;
private readonly FuncSubscriber<string> _penumbraResolveModDir; private readonly FuncSubscriber<string> _penumbraResolveModDir;
private readonly FuncSubscriber<string[], string[], (string[], string[][])> _penumbraResolvePaths; private readonly FuncSubscriber<string[], string[], Task<(string[], string[][])>> _penumbraResolvePaths;
private readonly ParamsFuncSubscriber<ushort, IReadOnlyDictionary<string, string[]>?[]> _penumbraResourcePaths; private readonly ParamsFuncSubscriber<ushort, IReadOnlyDictionary<string, string[]>?[]> _penumbraResourcePaths;
private readonly SemaphoreSlim _redrawSemaphore = new(2); private readonly SemaphoreSlim _redrawSemaphore = new(2);
private readonly uint LockCode = 0x6D617265; private readonly uint LockCode = 0x6D617265;
@@ -80,6 +80,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
public IpcManager(ILogger<IpcManager> logger, DalamudPluginInterface pi, DalamudUtilService dalamudUtil, MareMediator mediator) : base(logger, mediator) public IpcManager(ILogger<IpcManager> logger, DalamudPluginInterface pi, DalamudUtilService dalamudUtil, MareMediator mediator) : base(logger, mediator)
{ {
_pi = pi;
_dalamudUtil = dalamudUtil; _dalamudUtil = dalamudUtil;
_penumbraInit = Penumbra.Api.Ipc.Initialized.Subscriber(pi, PenumbraInit); _penumbraInit = Penumbra.Api.Ipc.Initialized.Subscriber(pi, PenumbraInit);
@@ -87,7 +88,6 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
_penumbraResolveModDir = Penumbra.Api.Ipc.GetModDirectory.Subscriber(pi); _penumbraResolveModDir = Penumbra.Api.Ipc.GetModDirectory.Subscriber(pi);
_penumbraRedraw = Penumbra.Api.Ipc.RedrawObjectByName.Subscriber(pi); _penumbraRedraw = Penumbra.Api.Ipc.RedrawObjectByName.Subscriber(pi);
_penumbraRedrawObject = Penumbra.Api.Ipc.RedrawObject.Subscriber(pi); _penumbraRedrawObject = Penumbra.Api.Ipc.RedrawObject.Subscriber(pi);
_penumbraApiVersion = Penumbra.Api.Ipc.ApiVersions.Subscriber(pi);
_penumbraObjectIsRedrawn = Penumbra.Api.Ipc.GameObjectRedrawn.Subscriber(pi, RedrawEvent); _penumbraObjectIsRedrawn = Penumbra.Api.Ipc.GameObjectRedrawn.Subscriber(pi, RedrawEvent);
_penumbraGetMetaManipulations = Penumbra.Api.Ipc.GetPlayerMetaManipulations.Subscriber(pi); _penumbraGetMetaManipulations = Penumbra.Api.Ipc.GetPlayerMetaManipulations.Subscriber(pi);
_penumbraRemoveTemporaryMod = Penumbra.Api.Ipc.RemoveTemporaryMod.Subscriber(pi); _penumbraRemoveTemporaryMod = Penumbra.Api.Ipc.RemoveTemporaryMod.Subscriber(pi);
@@ -95,7 +95,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
_penumbraCreateNamedTemporaryCollection = Penumbra.Api.Ipc.CreateNamedTemporaryCollection.Subscriber(pi); _penumbraCreateNamedTemporaryCollection = Penumbra.Api.Ipc.CreateNamedTemporaryCollection.Subscriber(pi);
_penumbraRemoveTemporaryCollection = Penumbra.Api.Ipc.RemoveTemporaryCollectionByName.Subscriber(pi); _penumbraRemoveTemporaryCollection = Penumbra.Api.Ipc.RemoveTemporaryCollectionByName.Subscriber(pi);
_penumbraAssignTemporaryCollection = Penumbra.Api.Ipc.AssignTemporaryCollection.Subscriber(pi); _penumbraAssignTemporaryCollection = Penumbra.Api.Ipc.AssignTemporaryCollection.Subscriber(pi);
_penumbraResolvePaths = Penumbra.Api.Ipc.ResolvePlayerPaths.Subscriber(pi); _penumbraResolvePaths = Penumbra.Api.Ipc.ResolvePlayerPathsAsync.Subscriber(pi);
_penumbraEnabled = Penumbra.Api.Ipc.GetEnabledState.Subscriber(pi); _penumbraEnabled = Penumbra.Api.Ipc.GetEnabledState.Subscriber(pi);
_penumbraModSettingChanged = Penumbra.Api.Ipc.ModSettingChanged.Subscriber(pi, (change, arg1, arg, b) => _penumbraModSettingChanged = Penumbra.Api.Ipc.ModSettingChanged.Subscriber(pi, (change, arg1, arg, b) =>
{ {
@@ -569,7 +569,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
public async Task<(string[] forward, string[][] reverse)> PenumbraResolvePathsAsync(string[] forward, string[] reverse) public async Task<(string[] forward, string[][] reverse)> PenumbraResolvePathsAsync(string[] forward, string[] reverse)
{ {
return await _dalamudUtil.RunOnFrameworkThread(() => _penumbraResolvePaths.Invoke(forward, reverse)).ConfigureAwait(false); return await _penumbraResolvePaths.Invoke(forward, reverse).ConfigureAwait(false);
} }
public async Task PenumbraSetManipulationDataAsync(ILogger logger, Guid applicationId, string collName, string manipulationData) public async Task PenumbraSetManipulationDataAsync(ILogger logger, Guid applicationId, string collName, string manipulationData)
@@ -700,20 +700,23 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
private bool CheckPenumbraApiInternal() private bool CheckPenumbraApiInternal()
{ {
bool apiAvailable = false; bool penumbraAvailable = false;
try try
{ {
apiAvailable = _penumbraApiVersion.Invoke() is { Item1: 4, Item2: >= 21 } && _penumbraEnabled.Invoke(); penumbraAvailable = (_pi.InstalledPlugins
_shownPenumbraUnavailable = _shownPenumbraUnavailable && !apiAvailable; .FirstOrDefault(p => string.Equals(p.InternalName, "Penumbra", StringComparison.OrdinalIgnoreCase))
return apiAvailable; ?.Version ?? new Version(0, 0, 0, 0)) >= new Version(0, 8, 1, 6);
penumbraAvailable &= _penumbraEnabled.Invoke();
_shownPenumbraUnavailable = _shownPenumbraUnavailable && !penumbraAvailable;
return penumbraAvailable;
} }
catch catch
{ {
return apiAvailable; return penumbraAvailable;
} }
finally finally
{ {
if (!apiAvailable && !_shownPenumbraUnavailable) if (!penumbraAvailable && !_shownPenumbraUnavailable)
{ {
_shownPenumbraUnavailable = true; _shownPenumbraUnavailable = true;
Mediator.Publish(new NotificationMessage("Penumbra inactive", "Your Penumbra installation is not active or out of date. Update Penumbra and/or the Enable Mods setting in Penumbra to continue to use Mare.", NotificationType.Error)); Mediator.Publish(new NotificationMessage("Penumbra inactive", "Your Penumbra installation is not active or out of date. Update Penumbra and/or the Enable Mods setting in Penumbra to continue to use Mare.", NotificationType.Error));

View File

@@ -39,7 +39,7 @@
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.11" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.11" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="7.0.11" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="7.0.11" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Penumbra.Api" Version="1.0.11" /> <PackageReference Include="Penumbra.Api" Version="1.0.12" />
<PackageReference Include="Penumbra.String" Version="1.0.4" /> <PackageReference Include="Penumbra.String" Version="1.0.4" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.2" /> <PackageReference Include="SixLabors.ImageSharp" Version="3.0.2" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.11.0.78383"> <PackageReference Include="SonarAnalyzer.CSharp" Version="9.11.0.78383">

View File

@@ -183,7 +183,8 @@ public class CompactUi : WindowMediatorSubscriberBase
{ {
var ySize = TransferPartHeight == 0 var ySize = TransferPartHeight == 0
? 1 ? 1
: (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - TransferPartHeight - ImGui.GetCursorPosY(); : (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y
+ ImGui.GetTextLineHeight() - ImGui.GetStyle().WindowBorderSize) - TransferPartHeight - ImGui.GetCursorPosY();
ImGui.BeginChild("list", new Vector2(WindowContentWidth, ySize), border: false); ImGui.BeginChild("list", new Vector2(WindowContentWidth, ySize), border: false);

View File

@@ -678,13 +678,6 @@ public class SettingsUi : WindowMediatorSubscriberBase
Mediator.Publish(new CompactUiChange(Vector2.Zero, Vector2.Zero)); Mediator.Publish(new CompactUiChange(Vector2.Zero, Vector2.Zero));
} }
UiSharedService.DrawHelpText("Will show profiles on the right side of the main UI"); UiSharedService.DrawHelpText("Will show profiles on the right side of the main UI");
if (ImGui.Checkbox("Show profiles marked as NSFW", ref showNsfwProfiles))
{
Mediator.Publish(new ClearProfileDataMessage());
_configService.Current.ProfilesAllowNsfw = showNsfwProfiles;
_configService.Save();
}
UiSharedService.DrawHelpText("Will show profiles that have the NSFW tag enabled");
if (ImGui.SliderFloat("Hover Delay", ref profileDelay, 1, 10)) if (ImGui.SliderFloat("Hover Delay", ref profileDelay, 1, 10))
{ {
_configService.Current.ProfileDelay = profileDelay; _configService.Current.ProfileDelay = profileDelay;
@@ -693,6 +686,13 @@ public class SettingsUi : WindowMediatorSubscriberBase
UiSharedService.DrawHelpText("Delay until the profile should be displayed"); UiSharedService.DrawHelpText("Delay until the profile should be displayed");
if (!showProfiles) ImGui.EndDisabled(); if (!showProfiles) ImGui.EndDisabled();
ImGui.Unindent(); ImGui.Unindent();
if (ImGui.Checkbox("Show profiles marked as NSFW", ref showNsfwProfiles))
{
Mediator.Publish(new ClearProfileDataMessage());
_configService.Current.ProfilesAllowNsfw = showNsfwProfiles;
_configService.Save();
}
UiSharedService.DrawHelpText("Will show profiles that have the NSFW tag enabled");
ImGui.Separator(); ImGui.Separator();

View File

@@ -20,12 +20,12 @@ public class TopTabMenu
private readonly PairManager _pairManager; private readonly PairManager _pairManager;
private string _filter = string.Empty;
private int _globalControlCountdown = 0; private int _globalControlCountdown = 0;
private string _pairToAdd = string.Empty; private string _pairToAdd = string.Empty;
private SelectedTab _selectedTab = SelectedTab.None; private SelectedTab _selectedTab = SelectedTab.None;
public TopTabMenu(MareMediator mareMediator, ApiController apiController, PairManager pairManager) public TopTabMenu(MareMediator mareMediator, ApiController apiController, PairManager pairManager)
{ {
_mareMediator = mareMediator; _mareMediator = mareMediator;
@@ -41,8 +41,32 @@ public class TopTabMenu
Filter, Filter,
UserConfig UserConfig
} }
public string Filter { get; private set; } = string.Empty;
public string Filter
{
get => _filter;
private set
{
if (!string.Equals(_filter, value, StringComparison.OrdinalIgnoreCase))
{
_mareMediator.Publish(new RefreshUiMessage());
}
_filter = value;
}
}
private SelectedTab TabSelection
{
get => _selectedTab; set
{
if (_selectedTab == SelectedTab.Filter && value != SelectedTab.Filter)
{
Filter = string.Empty;
}
_selectedTab = value;
}
}
public void Draw() public void Draw()
{ {
var availableWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X; var availableWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
@@ -61,11 +85,11 @@ public class TopTabMenu
var x = ImGui.GetCursorScreenPos(); var x = ImGui.GetCursorScreenPos();
if (ImGui.Button(FontAwesomeIcon.User.ToIconString(), buttonSize)) if (ImGui.Button(FontAwesomeIcon.User.ToIconString(), buttonSize))
{ {
_selectedTab = _selectedTab == SelectedTab.Individual ? SelectedTab.None : SelectedTab.Individual; TabSelection = TabSelection == SelectedTab.Individual ? SelectedTab.None : SelectedTab.Individual;
} }
ImGui.SameLine(); ImGui.SameLine();
var xAfter = ImGui.GetCursorScreenPos(); var xAfter = ImGui.GetCursorScreenPos();
if (_selectedTab == SelectedTab.Individual) if (TabSelection == SelectedTab.Individual)
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y }, drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X }, xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
underlineColor, 2); underlineColor, 2);
@@ -77,11 +101,11 @@ public class TopTabMenu
var x = ImGui.GetCursorScreenPos(); var x = ImGui.GetCursorScreenPos();
if (ImGui.Button(FontAwesomeIcon.Users.ToIconString(), buttonSize)) if (ImGui.Button(FontAwesomeIcon.Users.ToIconString(), buttonSize))
{ {
_selectedTab = _selectedTab == SelectedTab.Syncshell ? SelectedTab.None : SelectedTab.Syncshell; TabSelection = TabSelection == SelectedTab.Syncshell ? SelectedTab.None : SelectedTab.Syncshell;
} }
ImGui.SameLine(); ImGui.SameLine();
var xAfter = ImGui.GetCursorScreenPos(); var xAfter = ImGui.GetCursorScreenPos();
if (_selectedTab == SelectedTab.Syncshell) if (TabSelection == SelectedTab.Syncshell)
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y }, drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X }, xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
underlineColor, 2); underlineColor, 2);
@@ -94,12 +118,12 @@ public class TopTabMenu
var x = ImGui.GetCursorScreenPos(); var x = ImGui.GetCursorScreenPos();
if (ImGui.Button(FontAwesomeIcon.Filter.ToIconString(), buttonSize)) if (ImGui.Button(FontAwesomeIcon.Filter.ToIconString(), buttonSize))
{ {
_selectedTab = _selectedTab == SelectedTab.Filter ? SelectedTab.None : SelectedTab.Filter; TabSelection = TabSelection == SelectedTab.Filter ? SelectedTab.None : SelectedTab.Filter;
} }
ImGui.SameLine(); ImGui.SameLine();
var xAfter = ImGui.GetCursorScreenPos(); var xAfter = ImGui.GetCursorScreenPos();
if (_selectedTab == SelectedTab.Filter) if (TabSelection == SelectedTab.Filter)
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y }, drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X }, xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
underlineColor, 2); underlineColor, 2);
@@ -112,12 +136,12 @@ public class TopTabMenu
var x = ImGui.GetCursorScreenPos(); var x = ImGui.GetCursorScreenPos();
if (ImGui.Button(FontAwesomeIcon.UserCog.ToIconString(), buttonSize)) if (ImGui.Button(FontAwesomeIcon.UserCog.ToIconString(), buttonSize))
{ {
_selectedTab = _selectedTab == SelectedTab.UserConfig ? SelectedTab.None : SelectedTab.UserConfig; TabSelection = TabSelection == SelectedTab.UserConfig ? SelectedTab.None : SelectedTab.UserConfig;
} }
ImGui.SameLine(); ImGui.SameLine();
var xAfter = ImGui.GetCursorScreenPos(); var xAfter = ImGui.GetCursorScreenPos();
if (_selectedTab == SelectedTab.UserConfig) if (TabSelection == SelectedTab.UserConfig)
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y }, drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X }, xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
underlineColor, 2); underlineColor, 2);
@@ -129,26 +153,26 @@ public class TopTabMenu
ImGuiHelpers.ScaledDummy(spacing); ImGuiHelpers.ScaledDummy(spacing);
if (_selectedTab == SelectedTab.Individual) if (TabSelection == SelectedTab.Individual)
{ {
DrawAddPair(availableWidth, spacing.X); DrawAddPair(availableWidth, spacing.X);
DrawGlobalIndividualButtons(availableWidth, spacing.X); DrawGlobalIndividualButtons(availableWidth, spacing.X);
} }
else if (_selectedTab == SelectedTab.Syncshell) else if (TabSelection == SelectedTab.Syncshell)
{ {
DrawSyncshellMenu(availableWidth, spacing.X); DrawSyncshellMenu(availableWidth, spacing.X);
DrawGlobalSyncshellButtons(availableWidth, spacing.X); DrawGlobalSyncshellButtons(availableWidth, spacing.X);
} }
else if (_selectedTab == SelectedTab.Filter) else if (TabSelection == SelectedTab.Filter)
{ {
DrawFilter(availableWidth); DrawFilter(availableWidth, spacing.X);
} }
else if (_selectedTab == SelectedTab.UserConfig) else if (TabSelection == SelectedTab.UserConfig)
{ {
DrawUserConfig(availableWidth, spacing.X); DrawUserConfig(availableWidth, spacing.X);
} }
if (_selectedTab != SelectedTab.None) ImGuiHelpers.ScaledDummy(3f); if (TabSelection != SelectedTab.None) ImGuiHelpers.ScaledDummy(3f);
ImGui.Separator(); ImGui.Separator();
ImGuiHelpers.ScaledDummy(1f); ImGuiHelpers.ScaledDummy(1f);
} }
@@ -171,14 +195,20 @@ public class TopTabMenu
UiSharedService.AttachToolTip("Pair with " + (_pairToAdd.IsNullOrEmpty() ? "other user" : _pairToAdd)); UiSharedService.AttachToolTip("Pair with " + (_pairToAdd.IsNullOrEmpty() ? "other user" : _pairToAdd));
} }
private void DrawFilter(float availableWidth) private void DrawFilter(float availableWidth, float spacingX)
{ {
ImGui.SetNextItemWidth(availableWidth); var buttonSize = UiSharedService.GetIconTextButtonSize(FontAwesomeIcon.Ban, "Clear");
ImGui.SetNextItemWidth(availableWidth - buttonSize.X - spacingX);
string filter = Filter; string filter = Filter;
if (ImGui.InputTextWithHint("##filter", "Filter for UID/notes", ref filter, 255)) if (ImGui.InputTextWithHint("##filter", "Filter for UID/notes", ref filter, 255))
{ {
Filter = filter; Filter = filter;
_mareMediator.Publish(new RefreshUiMessage()); }
ImGui.SameLine();
using var disabled = ImRaii.Disabled(string.IsNullOrEmpty(Filter));
if (UiSharedService.IconTextButton(FontAwesomeIcon.Ban, "Clear"))
{
Filter = string.Empty;
} }
} }
@@ -404,7 +434,7 @@ public class TopTabMenu
ImGui.SameLine(); ImGui.SameLine();
using (ImRaii.PushFont(UiBuilder.IconFont)) using (ImRaii.PushFont(UiBuilder.IconFont))
{ {
using var disabled = ImRaii.Disabled(_globalControlCountdown > 0); using var disabled = ImRaii.Disabled(_globalControlCountdown > 0 || !UiSharedService.CtrlPressed());
if (ImGui.Button(FontAwesomeIcon.Check.ToIconString(), buttonSize)) if (ImGui.Button(FontAwesomeIcon.Check.ToIconString(), buttonSize))
{ {
@@ -425,7 +455,8 @@ public class TopTabMenu
UiSharedService.AttachToolTip("Globally align syncshell permissions to suggested syncshell permissions." + UiSharedService.TooltipSeparator UiSharedService.AttachToolTip("Globally align syncshell permissions to suggested syncshell permissions." + UiSharedService.TooltipSeparator
+ "Note: This will not affect users with preferred permissions in syncshells." + Environment.NewLine + "Note: This will not affect users with preferred permissions in syncshells." + Environment.NewLine
+ "Note: If multiple users share one syncshell the permissions to that user will be set to " + Environment.NewLine + "Note: If multiple users share one syncshell the permissions to that user will be set to " + Environment.NewLine
+ "the ones of the last applied syncshell in alphabetical order." + "the ones of the last applied syncshell in alphabetical order." + UiSharedService.TooltipSeparator
+ "Hold CTRL to enable this button"
+ (_globalControlCountdown > 0 ? UiSharedService.TooltipSeparator + "Available again in " + _globalControlCountdown + " seconds." : string.Empty)); + (_globalControlCountdown > 0 ? UiSharedService.TooltipSeparator + "Available again in " + _globalControlCountdown + " seconds." : string.Empty));
} }