"Amélioration de l'UI AutoDetect Syncshell : ajout de paramètres récurrents, plages horaires et gestion des fuseaux horaires. Refactorisation des méthodes de dessin et introduction de boutons centrés pour une meilleure ergonomie. Mise à jour des fichiers de configuration et du projet avec des optimisations diverses."
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,6 +3,7 @@
|
|||||||
##
|
##
|
||||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
.idea
|
.idea
|
||||||
|
qodana.yaml
|
||||||
# User-specific files
|
# User-specific files
|
||||||
*.rsuser
|
*.rsuser
|
||||||
*.suo
|
*.suo
|
||||||
@@ -13,6 +14,8 @@
|
|||||||
MareSynchronos/.DS_Store
|
MareSynchronos/.DS_Store
|
||||||
*.zip
|
*.zip
|
||||||
UmbraServer_extracted/
|
UmbraServer_extracted/
|
||||||
|
NuGet.config
|
||||||
|
Directory.Build.props
|
||||||
|
|
||||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
*.userprefs
|
*.userprefs
|
||||||
|
|||||||
2
MareAPI
2
MareAPI
Submodule MareAPI updated: deb911cb0a...f75f16fb13
@@ -50,6 +50,8 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<SourceRevisionId>build$([System.DateTime]::UtcNow.ToString("yyyy-MM-ddTHH:mm:ss:fffZ"))</SourceRevisionId>
|
<SourceRevisionId>build$([System.DateTime]::UtcNow.ToString("yyyy-MM-ddTHH:mm:ss:fffZ"))</SourceRevisionId>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<DisablePackageVulnerabilityAnalysis>true</DisablePackageVulnerabilityAnalysis>
|
||||||
|
<NoWarn>$(NoWarn);NU1900</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -73,6 +73,13 @@ public sealed class SyncshellDiscoveryService : IHostedService, IMediatorSubscri
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> SetVisibilityAsync(string gid, bool visible, CancellationToken ct)
|
public async Task<bool> SetVisibilityAsync(string gid, bool visible, CancellationToken ct)
|
||||||
|
{
|
||||||
|
return await SetVisibilityAsync(gid, visible, null, null, null, null, null, ct).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> SetVisibilityAsync(string gid, bool visible, int? displayDurationHours,
|
||||||
|
int[]? activeWeekdays, TimeSpan? timeStartLocal, TimeSpan? timeEndLocal, string? timeZone,
|
||||||
|
CancellationToken ct)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -80,6 +87,11 @@ public sealed class SyncshellDiscoveryService : IHostedService, IMediatorSubscri
|
|||||||
{
|
{
|
||||||
GID = gid,
|
GID = gid,
|
||||||
AutoDetectVisible = visible,
|
AutoDetectVisible = visible,
|
||||||
|
DisplayDurationHours = displayDurationHours,
|
||||||
|
ActiveWeekdays = activeWeekdays,
|
||||||
|
TimeStartLocal = timeStartLocal.HasValue ? new DateTime(timeStartLocal.Value.Ticks).ToString("HH:mm") : null,
|
||||||
|
TimeEndLocal = timeEndLocal.HasValue ? new DateTime(timeEndLocal.Value.Ticks).ToString("HH:mm") : null,
|
||||||
|
TimeZone = timeZone,
|
||||||
};
|
};
|
||||||
var success = await _apiController.SyncshellDiscoverySetVisibility(request).ConfigureAwait(false);
|
var success = await _apiController.SyncshellDiscoverySetVisibility(request).ConfigureAwait(false);
|
||||||
if (!success) return false;
|
if (!success) return false;
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
width += _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Plus).X + spacing;
|
width += _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Plus).X + spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
width += spacing * 1.2f;
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,6 +217,7 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
var pauseIcon = _fullInfoDto.GroupUserPermissions.IsPaused() ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause;
|
var pauseIcon = _fullInfoDto.GroupUserPermissions.IsPaused() ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause;
|
||||||
var pauseButtonWidth = _uiSharedService.GetIconButtonSize(pauseIcon).X;
|
var pauseButtonWidth = _uiSharedService.GetIconButtonSize(pauseIcon).X;
|
||||||
var barButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars).X;
|
var barButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars).X;
|
||||||
|
var rightEdgeGap = spacing * 1.2f;
|
||||||
|
|
||||||
float totalWidth = 0f;
|
float totalWidth = 0f;
|
||||||
void Accumulate(bool condition, float width)
|
void Accumulate(bool condition, float width)
|
||||||
@@ -242,7 +245,7 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
float cardPaddingX = UiSharedService.GetCardContentPaddingX();
|
float cardPaddingX = UiSharedService.GetCardContentPaddingX();
|
||||||
float rightMargin = cardPaddingX + 6f * ImGuiHelpers.GlobalScale;
|
float rightMargin = cardPaddingX + 6f * ImGuiHelpers.GlobalScale;
|
||||||
float baseX = MathF.Max(ImGui.GetCursorPosX(),
|
float baseX = MathF.Max(ImGui.GetCursorPosX(),
|
||||||
ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - rightMargin - totalWidth);
|
ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - rightMargin - rightEdgeGap - totalWidth);
|
||||||
float currentX = baseX;
|
float currentX = baseX;
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
@@ -266,6 +269,16 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
|
|
||||||
if (showInfo && infoIconWidth > 0f)
|
if (showInfo && infoIconWidth > 0f)
|
||||||
{
|
{
|
||||||
|
bool centerWarning = permIcon == FontAwesomeIcon.ExclamationTriangle && showPause && showBars && !showShared && !showPlus;
|
||||||
|
if (centerWarning)
|
||||||
|
{
|
||||||
|
float barsClusterWidth = showBars ? (barButtonWidth + spacing * 0.5f) : 0f;
|
||||||
|
float leftAreaWidth = MathF.Max(totalWidth - pauseButtonWidth - barsClusterWidth, 0f);
|
||||||
|
float warningX = baseX + MathF.Max((leftAreaWidth - infoIconWidth) / 2f, 0f);
|
||||||
|
currentX = warningX;
|
||||||
|
ImGui.SetCursorPosX(currentX);
|
||||||
|
}
|
||||||
|
|
||||||
ImGui.SetCursorPosY(textPosY);
|
ImGui.SetCursorPosY(textPosY);
|
||||||
if (individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled)
|
if (individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled)
|
||||||
{
|
{
|
||||||
@@ -359,7 +372,7 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
{
|
{
|
||||||
ImGui.SetCursorPosY(originalY);
|
ImGui.SetCursorPosY(originalY);
|
||||||
|
|
||||||
if (_uiSharedService.IconButton(FontAwesomeIcon.Plus))
|
if (_uiSharedService.IconPlusButtonCentered())
|
||||||
{
|
{
|
||||||
var targetUid = _pair.UserData.UID;
|
var targetUid = _pair.UserData.UID;
|
||||||
if (!string.IsNullOrEmpty(targetUid))
|
if (!string.IsNullOrEmpty(targetUid))
|
||||||
@@ -376,7 +389,7 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
{
|
{
|
||||||
float gapToBars = showBars ? spacing * 0.5f : spacing;
|
float gapToBars = showBars ? spacing * 0.5f : spacing;
|
||||||
ImGui.SetCursorPosY(originalY);
|
ImGui.SetCursorPosY(originalY);
|
||||||
if (_uiSharedService.IconButton(pauseIcon))
|
if (pauseIcon == FontAwesomeIcon.Pause ? _uiSharedService.IconPauseButtonCentered() : _uiSharedService.IconButtonCentered(pauseIcon))
|
||||||
{
|
{
|
||||||
var newPermissions = _fullInfoDto.GroupUserPermissions ^ GroupUserPermissions.Paused;
|
var newPermissions = _fullInfoDto.GroupUserPermissions ^ GroupUserPermissions.Paused;
|
||||||
_fullInfoDto.GroupUserPermissions = newPermissions;
|
_fullInfoDto.GroupUserPermissions = newPermissions;
|
||||||
@@ -391,7 +404,7 @@ public class DrawGroupPair : DrawPairBase
|
|||||||
if (showBars)
|
if (showBars)
|
||||||
{
|
{
|
||||||
ImGui.SetCursorPosY(originalY);
|
ImGui.SetCursorPosY(originalY);
|
||||||
if (_uiSharedService.IconButton(FontAwesomeIcon.Bars))
|
if (_uiSharedService.IconButtonCentered(FontAwesomeIcon.Bars))
|
||||||
{
|
{
|
||||||
ImGui.OpenPopup("Syncshell Flyout Menu");
|
ImGui.OpenPopup("Syncshell Flyout Menu");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ public abstract class DrawPairBase
|
|||||||
var menuButtonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars);
|
var menuButtonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars);
|
||||||
|
|
||||||
float pauseClusterWidth = Math.Max(pauseButtonSize.X, playButtonSize.X);
|
float pauseClusterWidth = Math.Max(pauseButtonSize.X, playButtonSize.X);
|
||||||
float pauseClusterHeight = Math.Max(pauseButtonSize.Y, playButtonSize.Y);
|
float pauseClusterHeight = Math.Max(Math.Max(pauseButtonSize.Y, playButtonSize.Y), ImGui.GetFrameHeight());
|
||||||
float reservedSpacing = style.ItemSpacing.X * 2.4f;
|
float reservedSpacing = style.ItemSpacing.X * 1.6f;
|
||||||
float rightButtonWidth =
|
float rightButtonWidth =
|
||||||
menuButtonSize.X +
|
menuButtonSize.X +
|
||||||
pauseClusterWidth +
|
pauseClusterWidth +
|
||||||
@@ -84,11 +84,15 @@ public abstract class DrawPairBase
|
|||||||
|
|
||||||
ImGui.SetCursorPos(new Vector2(rowStartCursor.X + padding.X, iconTop));
|
ImGui.SetCursorPos(new Vector2(rowStartCursor.X + padding.X, iconTop));
|
||||||
DrawLeftSide(iconTop, iconTop);
|
DrawLeftSide(iconTop, iconTop);
|
||||||
ImGui.SameLine();
|
|
||||||
ImGui.SetCursorPosY(textTop);
|
float leftReserved = GetLeftSideReservedWidth();
|
||||||
var posX = ImGui.GetCursorPosX();
|
float nameStartX = rowStartCursor.X + padding.X + leftReserved;
|
||||||
|
|
||||||
var rightSide = DrawRightSide(buttonTop, buttonTop);
|
var rightSide = DrawRightSide(buttonTop, buttonTop);
|
||||||
DrawName(textTop + padding.Y * 0.15f, posX, rightSide);
|
|
||||||
|
ImGui.SameLine(nameStartX);
|
||||||
|
ImGui.SetCursorPosY(textTop);
|
||||||
|
DrawName(textTop + padding.Y * 0.15f, nameStartX, rightSide);
|
||||||
|
|
||||||
ImGui.SetCursorPos(new Vector2(rowStartCursor.X, rowStartCursor.Y + totalHeight));
|
ImGui.SetCursorPos(new Vector2(rowStartCursor.X, rowStartCursor.Y + totalHeight));
|
||||||
ImGui.SetCursorPosX(rowStartCursor.X);
|
ImGui.SetCursorPosX(rowStartCursor.X);
|
||||||
@@ -100,6 +104,8 @@ public abstract class DrawPairBase
|
|||||||
|
|
||||||
protected virtual float GetRightSideExtraWidth() => 0f;
|
protected virtual float GetRightSideExtraWidth() => 0f;
|
||||||
|
|
||||||
|
protected virtual float GetLeftSideReservedWidth() => UiSharedService.GetIconSize(FontAwesomeIcon.Moon).X * 2f + ImGui.GetStyle().ItemSpacing.X * 1.5f;
|
||||||
|
|
||||||
private void DrawName(float originalY, float leftSide, float rightSide)
|
private void DrawName(float originalY, float leftSide, float rightSide)
|
||||||
{
|
{
|
||||||
_displayHandler.DrawPairText(_id, _pair, leftSide, originalY, () => rightSide - leftSide);
|
_displayHandler.DrawPairText(_id, _pair, leftSide, originalY, () => rightSide - leftSide);
|
||||||
|
|||||||
@@ -60,8 +60,28 @@ public class DrawUserPair : DrawPairBase
|
|||||||
width += _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Running).X + spacingX * 0.5f;
|
width += _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Running).X + spacingX * 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
width += spacingX * 1.2f;
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override float GetLeftSideReservedWidth()
|
||||||
|
{
|
||||||
|
var style = ImGui.GetStyle();
|
||||||
|
float spacing = style.ItemSpacing.X;
|
||||||
|
float iconW = UiSharedService.GetIconSize(FontAwesomeIcon.Moon).X;
|
||||||
|
|
||||||
|
int icons = 1;
|
||||||
|
if (!(_pair.UserPair!.OwnPermissions.IsPaired() && _pair.UserPair!.OtherPermissions.IsPaired()))
|
||||||
|
icons++;
|
||||||
|
else if (_pair.UserPair!.OwnPermissions.IsPaused() || _pair.UserPair!.OtherPermissions.IsPaused())
|
||||||
|
icons++;
|
||||||
|
if (_pair.IsOnline && _pair.IsVisible)
|
||||||
|
icons++;
|
||||||
|
|
||||||
|
float iconsTotal = icons * iconW + Math.Max(0, icons - 1) * spacing;
|
||||||
|
float cushion = spacing * 0.6f;
|
||||||
|
return iconsTotal + cushion;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void DrawLeftSide(float textPosY, float originalY)
|
protected override void DrawLeftSide(float textPosY, float originalY)
|
||||||
{
|
{
|
||||||
@@ -133,7 +153,8 @@ public class DrawUserPair : DrawPairBase
|
|||||||
var entryUID = _pair.UserData.AliasOrUID;
|
var entryUID = _pair.UserData.AliasOrUID;
|
||||||
var spacingX = ImGui.GetStyle().ItemSpacing.X;
|
var spacingX = ImGui.GetStyle().ItemSpacing.X;
|
||||||
var edgePadding = UiSharedService.GetCardContentPaddingX() + 6f * ImGuiHelpers.GlobalScale;
|
var edgePadding = UiSharedService.GetCardContentPaddingX() + 6f * ImGuiHelpers.GlobalScale;
|
||||||
var windowEndX = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - edgePadding;
|
var rightEdgeGap = spacingX * 1.2f;
|
||||||
|
var windowEndX = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - edgePadding - rightEdgeGap;
|
||||||
var rightSidePos = windowEndX - barButtonSize.X;
|
var rightSidePos = windowEndX - barButtonSize.X;
|
||||||
|
|
||||||
// Flyout Menu
|
// Flyout Menu
|
||||||
@@ -150,13 +171,12 @@ public class DrawUserPair : DrawPairBase
|
|||||||
ImGui.EndPopup();
|
ImGui.EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pause (mutual pairs only)
|
|
||||||
if (_pair.UserPair!.OwnPermissions.IsPaired() && _pair.UserPair!.OtherPermissions.IsPaired())
|
if (_pair.UserPair!.OwnPermissions.IsPaired() && _pair.UserPair!.OtherPermissions.IsPaired())
|
||||||
{
|
{
|
||||||
rightSidePos -= pauseIconSize.X + spacingX;
|
rightSidePos -= pauseIconSize.X + spacingX;
|
||||||
ImGui.SameLine(rightSidePos);
|
ImGui.SameLine(rightSidePos);
|
||||||
ImGui.SetCursorPosY(originalY);
|
ImGui.SetCursorPosY(originalY);
|
||||||
if (_uiSharedService.IconButton(pauseIcon))
|
if (pauseIcon == FontAwesomeIcon.Pause ? _uiSharedService.IconPauseButtonCentered() : _uiSharedService.IconButtonCentered(pauseIcon))
|
||||||
{
|
{
|
||||||
var perm = _pair.UserPair!.OwnPermissions;
|
var perm = _pair.UserPair!.OwnPermissions;
|
||||||
perm.SetPaused(!perm.IsPaused());
|
perm.SetPaused(!perm.IsPaused());
|
||||||
|
|||||||
@@ -41,6 +41,16 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
|||||||
private bool _autoDetectVisible;
|
private bool _autoDetectVisible;
|
||||||
private bool _autoDetectPasswordDisabled;
|
private bool _autoDetectPasswordDisabled;
|
||||||
private string? _autoDetectMessage;
|
private string? _autoDetectMessage;
|
||||||
|
|
||||||
|
private bool _autoDetectDesiredVisibility;
|
||||||
|
private int _adDurationHours = 2;
|
||||||
|
private bool _adRecurring = false;
|
||||||
|
private readonly bool[] _adWeekdays = new bool[7];
|
||||||
|
private int _adStartHour = 21;
|
||||||
|
private int _adStartMinute = 0;
|
||||||
|
private int _adEndHour = 23;
|
||||||
|
private int _adEndMinute = 0;
|
||||||
|
private const string AutoDetectTimeZone = "Europe/Paris";
|
||||||
|
|
||||||
public SyncshellAdminUI(ILogger<SyncshellAdminUI> logger, MareMediator mediator, ApiController apiController,
|
public SyncshellAdminUI(ILogger<SyncshellAdminUI> logger, MareMediator mediator, ApiController apiController,
|
||||||
UiSharedService uiSharedService, PairManager pairManager, SyncshellDiscoveryService syncshellDiscoveryService,
|
UiSharedService uiSharedService, PairManager pairManager, SyncshellDiscoveryService syncshellDiscoveryService,
|
||||||
@@ -58,6 +68,7 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
|||||||
_multiInvites = 30;
|
_multiInvites = 30;
|
||||||
_pwChangeSuccess = true;
|
_pwChangeSuccess = true;
|
||||||
_autoDetectVisible = groupFullInfo.AutoDetectVisible;
|
_autoDetectVisible = groupFullInfo.AutoDetectVisible;
|
||||||
|
_autoDetectDesiredVisibility = _autoDetectVisible;
|
||||||
_autoDetectPasswordDisabled = groupFullInfo.PasswordTemporarilyDisabled;
|
_autoDetectPasswordDisabled = groupFullInfo.PasswordTemporarilyDisabled;
|
||||||
Mediator.Subscribe<SyncshellAutoDetectStateChanged>(this, OnSyncshellAutoDetectStateChanged);
|
Mediator.Subscribe<SyncshellAutoDetectStateChanged>(this, OnSyncshellAutoDetectStateChanged);
|
||||||
IsOpen = true;
|
IsOpen = true;
|
||||||
@@ -89,6 +100,9 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
|||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
var perm = GroupFullInfo.GroupPermissions;
|
var perm = GroupFullInfo.GroupPermissions;
|
||||||
|
|
||||||
|
using var tabColor = ImRaii.PushColor(ImGuiCol.Tab, UiSharedService.AccentColor);
|
||||||
|
using var tabHoverColor = ImRaii.PushColor(ImGuiCol.TabHovered, UiSharedService.AccentHoverColor);
|
||||||
|
using var tabActiveColor = ImRaii.PushColor(ImGuiCol.TabActive, UiSharedService.AccentActiveColor);
|
||||||
using var tabbar = ImRaii.TabBar("syncshell_tab_" + GroupFullInfo.GID);
|
using var tabbar = ImRaii.TabBar("syncshell_tab_" + GroupFullInfo.GID);
|
||||||
|
|
||||||
if (tabbar)
|
if (tabbar)
|
||||||
@@ -498,26 +512,93 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
|||||||
UiSharedService.ColorTextWrapped(_autoDetectMessage!, ImGuiColors.DalamudYellow);
|
UiSharedService.ColorTextWrapped(_autoDetectMessage!, ImGuiColors.DalamudYellow);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool desiredVisibility = _autoDetectVisible;
|
|
||||||
using (ImRaii.Disabled(_autoDetectToggleInFlight || _autoDetectStateLoading))
|
using (ImRaii.Disabled(_autoDetectToggleInFlight || _autoDetectStateLoading))
|
||||||
{
|
{
|
||||||
if (ImGui.Checkbox("Afficher cette Syncshell dans l'AutoDetect", ref desiredVisibility))
|
if (ImGui.Checkbox("Afficher cette Syncshell dans l'AutoDetect", ref _autoDetectDesiredVisibility))
|
||||||
{
|
{
|
||||||
_ = ToggleAutoDetectAsync(desiredVisibility);
|
// Only change local desired state; sending is done via the validate button
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_uiSharedService.DrawHelpText("Quand cette option est activée, le mot de passe devient inactif tant que la visibilité est maintenue.");
|
_uiSharedService.DrawHelpText("Quand cette option est activée, le mot de passe devient inactif tant que la visibilité est maintenue.");
|
||||||
|
|
||||||
|
if (_autoDetectDesiredVisibility)
|
||||||
|
{
|
||||||
|
ImGuiHelpers.ScaledDummy(4);
|
||||||
|
ImGui.TextUnformatted("Options d'affichage AutoDetect");
|
||||||
|
ImGui.Separator();
|
||||||
|
|
||||||
|
// Recurring toggle first
|
||||||
|
ImGui.Checkbox("Affichage récurrent", ref _adRecurring);
|
||||||
|
_uiSharedService.DrawHelpText("Si activé, vous pouvez choisir les jours et une plage horaire récurrents. Si désactivé, seule la durée sera prise en compte.");
|
||||||
|
|
||||||
|
// Duration in hours (only when NOT recurring)
|
||||||
|
if (!_adRecurring)
|
||||||
|
{
|
||||||
|
ImGuiHelpers.ScaledDummy(4);
|
||||||
|
int duration = _adDurationHours;
|
||||||
|
ImGui.PushItemWidth(120 * ImGuiHelpers.GlobalScale);
|
||||||
|
if (ImGui.InputInt("Durée (heures)", ref duration))
|
||||||
|
{
|
||||||
|
_adDurationHours = Math.Clamp(duration, 1, 240);
|
||||||
|
}
|
||||||
|
ImGui.PopItemWidth();
|
||||||
|
_uiSharedService.DrawHelpText("Combien de temps la Syncshell doit rester visible, en heures.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGuiHelpers.ScaledDummy(4);
|
||||||
|
if (_adRecurring)
|
||||||
|
{
|
||||||
|
ImGuiHelpers.ScaledDummy(4);
|
||||||
|
ImGui.TextUnformatted("Jours de la semaine actifs :");
|
||||||
|
string[] daysFr = new[] { "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim" };
|
||||||
|
for (int i = 0; i < 7; i++)
|
||||||
|
{
|
||||||
|
ImGui.SameLine(i == 0 ? 0 : 0);
|
||||||
|
bool v = _adWeekdays[i];
|
||||||
|
if (ImGui.Checkbox($"##adwd{i}", ref v)) _adWeekdays[i] = v;
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.TextUnformatted(daysFr[i]);
|
||||||
|
if (i < 6) ImGui.SameLine();
|
||||||
|
}
|
||||||
|
ImGui.NewLine();
|
||||||
|
_uiSharedService.DrawHelpText("Sélectionnez les jours où l'affichage est autorisé (ex: jeudi et dimanche).");
|
||||||
|
|
||||||
|
ImGuiHelpers.ScaledDummy(4);
|
||||||
|
ImGui.TextUnformatted("Plage horaire (heure locale Europe/Paris) :");
|
||||||
|
ImGui.PushItemWidth(60 * ImGuiHelpers.GlobalScale);
|
||||||
|
ImGui.InputInt("Début heure", ref _adStartHour); ImGui.SameLine();
|
||||||
|
ImGui.InputInt("min", ref _adStartMinute);
|
||||||
|
_adStartHour = Math.Clamp(_adStartHour, 0, 23);
|
||||||
|
_adStartMinute = Math.Clamp(_adStartMinute, 0, 59);
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.TextUnformatted("→"); ImGui.SameLine();
|
||||||
|
ImGui.InputInt("Fin heure", ref _adEndHour); ImGui.SameLine();
|
||||||
|
ImGui.InputInt("min ", ref _adEndMinute);
|
||||||
|
_adEndHour = Math.Clamp(_adEndHour, 0, 23);
|
||||||
|
_adEndMinute = Math.Clamp(_adEndMinute, 0, 59);
|
||||||
|
ImGui.PopItemWidth();
|
||||||
|
_uiSharedService.DrawHelpText("Exemple : de 21h00 à 23h00. Le fuseau utilisé est Europe/Paris (avec changements été/hiver).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_autoDetectPasswordDisabled && _autoDetectVisible)
|
if (_autoDetectPasswordDisabled && _autoDetectVisible)
|
||||||
{
|
{
|
||||||
UiSharedService.ColorTextWrapped("Le mot de passe est actuellement désactivé pendant la visibilité AutoDetect.", ImGuiColors.DalamudYellow);
|
UiSharedService.ColorTextWrapped("Le mot de passe est actuellement désactivé pendant la visibilité AutoDetect.", ImGuiColors.DalamudYellow);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuiHelpers.ScaledDummy(6);
|
ImGuiHelpers.ScaledDummy(6);
|
||||||
if (ImGui.Button("Recharger l'état"))
|
using (ImRaii.Disabled(_autoDetectToggleInFlight || _autoDetectStateLoading))
|
||||||
{
|
{
|
||||||
_autoDetectStateLoading = true;
|
if (ImGui.Button("Valider et envoyer"))
|
||||||
_ = EnsureAutoDetectStateAsync(true);
|
{
|
||||||
|
_ = SubmitAutoDetectAsync();
|
||||||
|
}
|
||||||
|
ImGui.SameLine();
|
||||||
|
if (ImGui.Button("Recharger l'état"))
|
||||||
|
{
|
||||||
|
_autoDetectStateLoading = true;
|
||||||
|
_ = EnsureAutoDetectStateAsync(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,6 +661,67 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task SubmitAutoDetectAsync()
|
||||||
|
{
|
||||||
|
if (_autoDetectToggleInFlight)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_autoDetectToggleInFlight = true;
|
||||||
|
_autoDetectMessage = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Duration always used when visible
|
||||||
|
int? duration = _autoDetectDesiredVisibility ? _adDurationHours : null;
|
||||||
|
|
||||||
|
// Scheduling fields only if recurring is enabled
|
||||||
|
int[]? weekdaysArr = null;
|
||||||
|
TimeSpan? start = null;
|
||||||
|
TimeSpan? end = null;
|
||||||
|
string? tz = null;
|
||||||
|
if (_autoDetectDesiredVisibility && _adRecurring)
|
||||||
|
{
|
||||||
|
List<int> weekdays = new();
|
||||||
|
for (int i = 0; i < 7; i++) if (_adWeekdays[i]) weekdays.Add(i);
|
||||||
|
weekdaysArr = weekdays.Count > 0 ? weekdays.ToArray() : Array.Empty<int>();
|
||||||
|
start = new TimeSpan(_adStartHour, _adStartMinute, 0);
|
||||||
|
end = new TimeSpan(_adEndHour, _adEndMinute, 0);
|
||||||
|
tz = AutoDetectTimeZone;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ok = await _syncshellDiscoveryService.SetVisibilityAsync(
|
||||||
|
GroupFullInfo.GID,
|
||||||
|
_autoDetectDesiredVisibility,
|
||||||
|
duration,
|
||||||
|
weekdaysArr,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
tz,
|
||||||
|
CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
_autoDetectMessage = "Impossible d'envoyer les paramètres AutoDetect.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await EnsureAutoDetectStateAsync(true).ConfigureAwait(false);
|
||||||
|
_autoDetectMessage = _autoDetectDesiredVisibility
|
||||||
|
? "Paramètres AutoDetect envoyés. La Syncshell sera visible selon le planning défini."
|
||||||
|
: "La Syncshell n'est plus visible dans AutoDetect.";
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_autoDetectMessage = $"Erreur lors de l'envoi des paramètres AutoDetect : {ex.Message}";
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_autoDetectToggleInFlight = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ApplyAutoDetectState(bool visible, bool passwordDisabled, bool fromServer)
|
private void ApplyAutoDetectState(bool visible, bool passwordDisabled, bool fromServer)
|
||||||
{
|
{
|
||||||
_autoDetectVisible = visible;
|
_autoDetectVisible = visible;
|
||||||
|
|||||||
@@ -541,6 +541,100 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IconButtonCentered(FontAwesomeIcon icon, float? height = null, float xOffset = 0f, float yOffset = 0f, bool square = false)
|
||||||
|
{
|
||||||
|
string text = icon.ToIconString();
|
||||||
|
|
||||||
|
ImGui.PushID($"centered-{text}");
|
||||||
|
Vector2 glyphSize;
|
||||||
|
using (IconFont.Push())
|
||||||
|
glyphSize = ImGui.CalcTextSize(text);
|
||||||
|
ImDrawListPtr drawList = ImGui.GetWindowDrawList();
|
||||||
|
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
|
||||||
|
float frameHeight = height ?? ImGui.GetFrameHeight();
|
||||||
|
float buttonWidth = square ? frameHeight : glyphSize.X + ImGui.GetStyle().FramePadding.X * 2f;
|
||||||
|
using var hoverColor = ImRaii.PushColor(ImGuiCol.ButtonHovered, AccentHoverColor);
|
||||||
|
using var activeColor = ImRaii.PushColor(ImGuiCol.ButtonActive, AccentActiveColor);
|
||||||
|
bool clicked = ImGui.Button(string.Empty, new Vector2(buttonWidth, frameHeight));
|
||||||
|
Vector2 pos = new Vector2(
|
||||||
|
cursorScreenPos.X + (buttonWidth - glyphSize.X) / 2f + xOffset,
|
||||||
|
cursorScreenPos.Y + frameHeight / 2f - glyphSize.Y / 2f + yOffset);
|
||||||
|
using (IconFont.Push())
|
||||||
|
drawList.AddText(pos, ImGui.GetColorU32(ImGuiCol.Text), text);
|
||||||
|
ImGui.PopID();
|
||||||
|
|
||||||
|
return clicked;
|
||||||
|
}
|
||||||
|
public bool IconPauseButtonCentered(float? height = null)
|
||||||
|
{
|
||||||
|
ImGui.PushID("centered-pause-custom");
|
||||||
|
Vector2 glyphSize;
|
||||||
|
using (IconFont.Push())
|
||||||
|
glyphSize = ImGui.CalcTextSize(FontAwesomeIcon.Pause.ToIconString());
|
||||||
|
float frameHeight = height ?? ImGui.GetFrameHeight();
|
||||||
|
float buttonWidth = glyphSize.X + ImGui.GetStyle().FramePadding.X * 2f;
|
||||||
|
|
||||||
|
using var hoverColor = ImRaii.PushColor(ImGuiCol.ButtonHovered, AccentHoverColor);
|
||||||
|
using var activeColor = ImRaii.PushColor(ImGuiCol.ButtonActive, AccentActiveColor);
|
||||||
|
|
||||||
|
var drawList = ImGui.GetWindowDrawList();
|
||||||
|
var buttonTopLeft = ImGui.GetCursorScreenPos();
|
||||||
|
bool clicked = ImGui.Button(string.Empty, new Vector2(buttonWidth, frameHeight));
|
||||||
|
|
||||||
|
var textColor = ImGui.GetColorU32(ImGuiCol.Text);
|
||||||
|
|
||||||
|
float h = frameHeight * 0.55f; // bar height
|
||||||
|
float w = MathF.Max(1f, frameHeight * 0.16f); // bar width
|
||||||
|
float gap = MathF.Max(1f, w * 0.9f); // gap between bars
|
||||||
|
float total = 2f * w + gap;
|
||||||
|
|
||||||
|
float startX = buttonTopLeft.X + (buttonWidth - total) / 2f;
|
||||||
|
float startY = buttonTopLeft.Y + (frameHeight - h) / 2f;
|
||||||
|
float rounding = w * 0.35f;
|
||||||
|
|
||||||
|
drawList.AddRectFilled(new Vector2(startX, startY), new Vector2(startX + w, startY + h), textColor, rounding);
|
||||||
|
float rightX = startX + w + gap;
|
||||||
|
drawList.AddRectFilled(new Vector2(rightX, startY), new Vector2(rightX + w, startY + h), textColor, rounding);
|
||||||
|
|
||||||
|
ImGui.PopID();
|
||||||
|
return clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IconPlusButtonCentered(float? height = null)
|
||||||
|
{
|
||||||
|
ImGui.PushID("centered-plus-custom");
|
||||||
|
Vector2 glyphSize;
|
||||||
|
using (IconFont.Push())
|
||||||
|
glyphSize = ImGui.CalcTextSize(FontAwesomeIcon.Plus.ToIconString());
|
||||||
|
float frameHeight = height ?? ImGui.GetFrameHeight();
|
||||||
|
float buttonWidth = glyphSize.X + ImGui.GetStyle().FramePadding.X * 2f;
|
||||||
|
|
||||||
|
using var hoverColor = ImRaii.PushColor(ImGuiCol.ButtonHovered, AccentHoverColor);
|
||||||
|
using var activeColor = ImRaii.PushColor(ImGuiCol.ButtonActive, AccentActiveColor);
|
||||||
|
|
||||||
|
var drawList = ImGui.GetWindowDrawList();
|
||||||
|
var buttonTopLeft = ImGui.GetCursorScreenPos();
|
||||||
|
bool clicked = ImGui.Button(string.Empty, new Vector2(buttonWidth, frameHeight));
|
||||||
|
|
||||||
|
var color = ImGui.GetColorU32(ImGuiCol.Text);
|
||||||
|
|
||||||
|
float armThickness = MathF.Max(1f, frameHeight * 0.14f);
|
||||||
|
float crossSize = frameHeight * 0.55f; // total length of vertical/horizontal arms
|
||||||
|
float startX = buttonTopLeft.X + (buttonWidth - crossSize) / 2f;
|
||||||
|
float startY = buttonTopLeft.Y + (frameHeight - crossSize) / 2f;
|
||||||
|
float endX = startX + crossSize;
|
||||||
|
float endY = startY + crossSize;
|
||||||
|
float r = armThickness * 0.35f;
|
||||||
|
|
||||||
|
float hY1 = startY + (crossSize - armThickness) / 2f;
|
||||||
|
drawList.AddRectFilled(new Vector2(startX, hY1), new Vector2(endX, hY1 + armThickness), color, r);
|
||||||
|
float vX1 = startX + (crossSize - armThickness) / 2f;
|
||||||
|
drawList.AddRectFilled(new Vector2(vX1, startY), new Vector2(vX1 + armThickness, endY), color, r);
|
||||||
|
|
||||||
|
ImGui.PopID();
|
||||||
|
return clicked;
|
||||||
|
}
|
||||||
|
|
||||||
private bool IconTextButtonInternal(FontAwesomeIcon icon, string text, Vector4? defaultColor = null, float? width = null, bool useAccentHover = true)
|
private bool IconTextButtonInternal(FontAwesomeIcon icon, string text, Vector4? defaultColor = null, float? width = null, bool useAccentHover = true)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user