mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-25 18:09:17 +01:00
Add Reduced Motion for Notifications (#1732)
When Reduced Motion configuration is on, the expiry progressbar is removed, and instead a pie on top right is shown, and relative time update interval increases to 15 seconds. Progress wave animation also is suppressed.
This commit is contained in:
parent
fb60ac5b4b
commit
95defa200f
6 changed files with 185 additions and 49 deletions
|
|
@ -367,6 +367,11 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ShowTsm { get; set; } = true;
|
public bool ShowTsm { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether to reduce motions (animations).
|
||||||
|
/// </summary>
|
||||||
|
public bool ReduceMotions { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether or not market board data should be uploaded.
|
/// Gets or sets a value indicating whether or not market board data should be uploaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.Internal;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
@ -20,8 +21,8 @@ internal sealed partial class ActiveNotification
|
||||||
var opacity =
|
var opacity =
|
||||||
Math.Clamp(
|
Math.Clamp(
|
||||||
(float)(this.hideEasing.IsRunning
|
(float)(this.hideEasing.IsRunning
|
||||||
? (this.hideEasing.IsDone ? 0 : 1f - this.hideEasing.Value)
|
? (this.hideEasing.IsDone || ReducedMotions ? 0 : 1f - this.hideEasing.Value)
|
||||||
: (this.showEasing.IsDone ? 1 : this.showEasing.Value)),
|
: (this.showEasing.IsDone || ReducedMotions ? 1 : this.showEasing.Value)),
|
||||||
0f,
|
0f,
|
||||||
1f);
|
1f);
|
||||||
if (opacity <= 0)
|
if (opacity <= 0)
|
||||||
|
|
@ -97,24 +98,25 @@ internal sealed partial class ActiveNotification
|
||||||
this.lastInterestTime = DateTime.Now;
|
this.lastInterestTime = DateTime.Now;
|
||||||
|
|
||||||
this.DrawWindowBackgroundProgressBar();
|
this.DrawWindowBackgroundProgressBar();
|
||||||
this.DrawTopBar(width, actionWindowHeight, isHovered);
|
this.DrawTopBar(width, actionWindowHeight, isHovered, warrantsExtension);
|
||||||
if (!this.underlyingNotification.Minimized && !this.expandoEasing.IsRunning)
|
if (!this.underlyingNotification.Minimized && !this.expandoEasing.IsRunning)
|
||||||
{
|
{
|
||||||
this.DrawContentAndActions(width, actionWindowHeight);
|
this.DrawContentAndActions(width, actionWindowHeight);
|
||||||
}
|
}
|
||||||
else if (this.expandoEasing.IsRunning)
|
else if (this.expandoEasing.IsRunning)
|
||||||
{
|
{
|
||||||
|
var easedValue = ReducedMotions ? 1f : (float)this.expandoEasing.Value;
|
||||||
if (this.underlyingNotification.Minimized)
|
if (this.underlyingNotification.Minimized)
|
||||||
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, opacity * (1f - (float)this.expandoEasing.Value));
|
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, opacity * (1f - easedValue));
|
||||||
else
|
else
|
||||||
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, opacity * (float)this.expandoEasing.Value);
|
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, opacity * easedValue);
|
||||||
this.DrawContentAndActions(width, actionWindowHeight);
|
this.DrawContentAndActions(width, actionWindowHeight);
|
||||||
ImGui.PopStyleVar();
|
ImGui.PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFocused)
|
if (isFocused)
|
||||||
this.DrawFocusIndicator();
|
this.DrawFocusIndicator();
|
||||||
this.DrawExpiryBar(this.EffectiveExpiry, warrantsExtension);
|
this.DrawExpiryBar(warrantsExtension);
|
||||||
|
|
||||||
if (ImGui.IsWindowHovered())
|
if (ImGui.IsWindowHovered())
|
||||||
{
|
{
|
||||||
|
|
@ -184,24 +186,36 @@ internal sealed partial class ActiveNotification
|
||||||
|
|
||||||
private void DrawWindowBackgroundProgressBar()
|
private void DrawWindowBackgroundProgressBar()
|
||||||
{
|
{
|
||||||
var elapsed = (float)(((DateTime.Now - this.CreatedAt).TotalMilliseconds %
|
var elapsed = 0f;
|
||||||
NotificationConstants.ProgressWaveLoopDuration) /
|
var colorElapsed = 0f;
|
||||||
NotificationConstants.ProgressWaveLoopDuration);
|
float progress;
|
||||||
elapsed /= NotificationConstants.ProgressWaveIdleTimeRatio;
|
|
||||||
|
|
||||||
var colorElapsed =
|
if (ReducedMotions)
|
||||||
elapsed < NotificationConstants.ProgressWaveLoopMaxColorTimeRatio
|
{
|
||||||
? elapsed / NotificationConstants.ProgressWaveLoopMaxColorTimeRatio
|
progress = this.Progress;
|
||||||
: ((NotificationConstants.ProgressWaveLoopMaxColorTimeRatio * 2) - elapsed) /
|
}
|
||||||
NotificationConstants.ProgressWaveLoopMaxColorTimeRatio;
|
else
|
||||||
|
{
|
||||||
|
progress = Math.Clamp(this.ProgressEased, 0f, 1f);
|
||||||
|
|
||||||
elapsed = Math.Clamp(elapsed, 0f, 1f);
|
elapsed =
|
||||||
colorElapsed = Math.Clamp(colorElapsed, 0f, 1f);
|
(float)(((DateTime.Now - this.CreatedAt).TotalMilliseconds %
|
||||||
colorElapsed = MathF.Sin(colorElapsed * (MathF.PI / 2f));
|
NotificationConstants.ProgressWaveLoopDuration) /
|
||||||
|
NotificationConstants.ProgressWaveLoopDuration);
|
||||||
|
elapsed /= NotificationConstants.ProgressWaveIdleTimeRatio;
|
||||||
|
|
||||||
var progress = Math.Clamp(this.ProgressEased, 0f, 1f);
|
colorElapsed = elapsed < NotificationConstants.ProgressWaveLoopMaxColorTimeRatio
|
||||||
if (progress >= 1f)
|
? elapsed / NotificationConstants.ProgressWaveLoopMaxColorTimeRatio
|
||||||
elapsed = colorElapsed = 0f;
|
: ((NotificationConstants.ProgressWaveLoopMaxColorTimeRatio * 2) - elapsed) /
|
||||||
|
NotificationConstants.ProgressWaveLoopMaxColorTimeRatio;
|
||||||
|
|
||||||
|
elapsed = Math.Clamp(elapsed, 0f, 1f);
|
||||||
|
colorElapsed = Math.Clamp(colorElapsed, 0f, 1f);
|
||||||
|
colorElapsed = MathF.Sin(colorElapsed * (MathF.PI / 2f));
|
||||||
|
|
||||||
|
if (progress >= 1f)
|
||||||
|
elapsed = colorElapsed = 0f;
|
||||||
|
}
|
||||||
|
|
||||||
var windowPos = ImGui.GetWindowPos();
|
var windowPos = ImGui.GetWindowPos();
|
||||||
var windowSize = ImGui.GetWindowSize();
|
var windowSize = ImGui.GetWindowSize();
|
||||||
|
|
@ -240,7 +254,7 @@ internal sealed partial class ActiveNotification
|
||||||
ImGui.PopClipRect();
|
ImGui.PopClipRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawTopBar(float width, float height, bool drawActionButtons)
|
private void DrawTopBar(float width, float height, bool drawActionButtons, bool warrantsExtension)
|
||||||
{
|
{
|
||||||
var windowPos = ImGui.GetWindowPos();
|
var windowPos = ImGui.GetWindowPos();
|
||||||
var windowSize = ImGui.GetWindowSize();
|
var windowSize = ImGui.GetWindowSize();
|
||||||
|
|
@ -249,6 +263,10 @@ internal sealed partial class ActiveNotification
|
||||||
using (Service<InterfaceManager>.Get().IconFontHandle?.Push())
|
using (Service<InterfaceManager>.Get().IconFontHandle?.Push())
|
||||||
{
|
{
|
||||||
ImGui.PushClipRect(windowPos, windowPos + windowSize with { Y = height }, false);
|
ImGui.PushClipRect(windowPos, windowPos + windowSize with { Y = height }, false);
|
||||||
|
|
||||||
|
if (!drawActionButtons)
|
||||||
|
this.DrawExpiryPie(warrantsExtension, new(width - height, 0), new(height));
|
||||||
|
|
||||||
if (this.UserDismissable)
|
if (this.UserDismissable)
|
||||||
{
|
{
|
||||||
if (this.DrawIconButton(FontAwesomeIcon.Times, rtOffset, height, drawActionButtons))
|
if (this.DrawIconButton(FontAwesomeIcon.Times, rtOffset, height, drawActionButtons))
|
||||||
|
|
@ -272,7 +290,7 @@ internal sealed partial class ActiveNotification
|
||||||
}
|
}
|
||||||
|
|
||||||
float relativeOpacity;
|
float relativeOpacity;
|
||||||
if (this.expandoEasing.IsRunning)
|
if (this.expandoEasing.IsRunning && !ReducedMotions)
|
||||||
{
|
{
|
||||||
relativeOpacity =
|
relativeOpacity =
|
||||||
this.underlyingNotification.Minimized
|
this.underlyingNotification.Minimized
|
||||||
|
|
@ -297,36 +315,35 @@ internal sealed partial class ActiveNotification
|
||||||
ImGui.TextUnformatted(
|
ImGui.TextUnformatted(
|
||||||
ImGui.IsWindowHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem)
|
ImGui.IsWindowHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem)
|
||||||
? this.CreatedAt.LocAbsolute()
|
? this.CreatedAt.LocAbsolute()
|
||||||
: this.CreatedAt.LocRelativePastLong());
|
: ReducedMotions
|
||||||
|
? this.CreatedAt.LocRelativePastLong(TimeSpan.FromSeconds(15))
|
||||||
|
: this.CreatedAt.LocRelativePastLong(TimeSpan.FromSeconds(5)));
|
||||||
ImGui.PopStyleColor();
|
ImGui.PopStyleColor();
|
||||||
ImGui.PopStyleVar();
|
ImGui.PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (relativeOpacity < 1)
|
if (relativeOpacity < 1)
|
||||||
{
|
{
|
||||||
rtOffset = new(width - NotificationConstants.ScaledWindowPadding, 0);
|
|
||||||
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * (1f - relativeOpacity));
|
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * (1f - relativeOpacity));
|
||||||
|
|
||||||
var ltOffset = new Vector2(NotificationConstants.ScaledWindowPadding);
|
var agoText =
|
||||||
this.DrawIcon(ltOffset, new(height - (2 * NotificationConstants.ScaledWindowPadding)));
|
ReducedMotions
|
||||||
|
? this.CreatedAt.LocRelativePastShort(TimeSpan.FromSeconds(15))
|
||||||
ltOffset.X = height;
|
: this.CreatedAt.LocRelativePastShort(TimeSpan.FromSeconds(5));
|
||||||
|
|
||||||
var agoText = this.CreatedAt.LocRelativePastShort();
|
|
||||||
var agoSize = ImGui.CalcTextSize(agoText);
|
var agoSize = ImGui.CalcTextSize(agoText);
|
||||||
rtOffset.X -= agoSize.X;
|
ImGui.SetCursorPos(new(width - ((height + agoSize.X) / 2f), NotificationConstants.ScaledWindowPadding));
|
||||||
ImGui.SetCursorPos(rtOffset with { Y = NotificationConstants.ScaledWindowPadding });
|
|
||||||
ImGui.PushStyleColor(ImGuiCol.Text, NotificationConstants.WhenTextColor);
|
ImGui.PushStyleColor(ImGuiCol.Text, NotificationConstants.WhenTextColor);
|
||||||
ImGui.TextUnformatted(agoText);
|
ImGui.TextUnformatted(agoText);
|
||||||
ImGui.PopStyleColor();
|
ImGui.PopStyleColor();
|
||||||
|
|
||||||
rtOffset.X -= NotificationConstants.ScaledWindowPadding;
|
this.DrawIcon(
|
||||||
|
new(NotificationConstants.ScaledWindowPadding),
|
||||||
|
new(height - (2 * NotificationConstants.ScaledWindowPadding)));
|
||||||
ImGui.PushClipRect(
|
ImGui.PushClipRect(
|
||||||
windowPos + ltOffset with { Y = 0 },
|
windowPos + new Vector2(height, 0),
|
||||||
windowPos + rtOffset with { Y = height },
|
windowPos + new Vector2(width - height, height),
|
||||||
true);
|
true);
|
||||||
ImGui.SetCursorPos(ltOffset with { Y = NotificationConstants.ScaledWindowPadding });
|
ImGui.SetCursorPos(new(height, NotificationConstants.ScaledWindowPadding));
|
||||||
ImGui.TextUnformatted(this.EffectiveMinimizedText);
|
ImGui.TextUnformatted(this.EffectiveMinimizedText);
|
||||||
ImGui.PopClipRect();
|
ImGui.PopClipRect();
|
||||||
|
|
||||||
|
|
@ -437,12 +454,95 @@ internal sealed partial class ActiveNotification
|
||||||
ImGui.PopTextWrapPos();
|
ImGui.PopTextWrapPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawExpiryBar(DateTime effectiveExpiry, bool warrantsExtension)
|
private void DrawExpiryPie(bool warrantsExtension, Vector2 offset, Vector2 size)
|
||||||
{
|
{
|
||||||
|
if (!Service<DalamudConfiguration>.Get().ReduceMotions)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// circle here; 0 means 0deg; 1 means 360deg
|
||||||
|
float fillStartCw, fillEndCw;
|
||||||
|
if (this.DismissReason is not null)
|
||||||
|
{
|
||||||
|
fillStartCw = fillEndCw = 0f;
|
||||||
|
}
|
||||||
|
else if (warrantsExtension)
|
||||||
|
{
|
||||||
|
fillStartCw = fillEndCw = 0f;
|
||||||
|
}
|
||||||
|
else if (this.EffectiveExpiry == DateTime.MaxValue)
|
||||||
|
{
|
||||||
|
if (this.ShowIndeterminateIfNoExpiry)
|
||||||
|
{
|
||||||
|
// draw
|
||||||
|
var elapsed = (float)(((DateTime.Now - this.CreatedAt).TotalMilliseconds %
|
||||||
|
NotificationConstants.IndeterminatePieLoopDuration) /
|
||||||
|
NotificationConstants.IndeterminatePieLoopDuration);
|
||||||
|
fillStartCw = elapsed;
|
||||||
|
fillEndCw = elapsed + 0.2f + (MathF.Sin(elapsed * MathF.PI) * 0.2f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// do not draw
|
||||||
|
fillStartCw = fillEndCw = 0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fillStartCw = 1f - (float)((this.EffectiveExpiry - DateTime.Now).TotalMilliseconds /
|
||||||
|
(this.EffectiveExpiry - this.lastInterestTime).TotalMilliseconds);
|
||||||
|
fillEndCw = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fillStartCw > fillEndCw)
|
||||||
|
(fillStartCw, fillEndCw) = (fillEndCw, fillStartCw);
|
||||||
|
|
||||||
|
if (fillStartCw == 0 && fillEndCw == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var radius = Math.Min(size.X, size.Y) / 3f;
|
||||||
|
var ifrom = fillStartCw * MathF.PI * 2;
|
||||||
|
var ito = fillEndCw * MathF.PI * 2;
|
||||||
|
|
||||||
|
var nseg = MathF.Ceiling(2 * MathF.PI * radius);
|
||||||
|
var step = (MathF.PI * 2) / nseg;
|
||||||
|
|
||||||
|
var center = ImGui.GetWindowPos() + offset + (size / 2);
|
||||||
|
var color = ImGui.GetColorU32(this.Type.ToColor() * new Vector4(1, 1, 1, 0.2f));
|
||||||
|
|
||||||
|
var prevOff = center + (radius * new Vector2(MathF.Sin(ifrom), -MathF.Cos(ifrom)));
|
||||||
|
Span<Vector2> verts = stackalloc Vector2[(int)MathF.Ceiling(((ito - ifrom) / step) + 3)];
|
||||||
|
var vertPtr = 0;
|
||||||
|
verts[vertPtr++] = center;
|
||||||
|
verts[vertPtr++] = prevOff;
|
||||||
|
|
||||||
|
var cur = ifrom + step;
|
||||||
|
for (; cur < ito; cur += step)
|
||||||
|
{
|
||||||
|
var curOff = center + (radius * new Vector2(MathF.Sin(cur), -MathF.Cos(cur)));
|
||||||
|
if (Vector2.DistanceSquared(prevOff, curOff) >= 1)
|
||||||
|
verts[vertPtr++] = prevOff = curOff;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastOff = center + (radius * new Vector2(MathF.Sin(ito), -MathF.Cos(ito)));
|
||||||
|
if (Vector2.DistanceSquared(prevOff, lastOff) >= 1)
|
||||||
|
verts[vertPtr++] = lastOff;
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
var dlist = ImGui.GetWindowDrawList().NativePtr;
|
||||||
|
fixed (Vector2* pvert = verts)
|
||||||
|
ImGuiNative.ImDrawList_AddConvexPolyFilled(dlist, pvert, vertPtr, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawExpiryBar(bool warrantsExtension)
|
||||||
|
{
|
||||||
|
if (Service<DalamudConfiguration>.Get().ReduceMotions)
|
||||||
|
return;
|
||||||
|
|
||||||
float barL, barR;
|
float barL, barR;
|
||||||
if (this.DismissReason is not null)
|
if (this.DismissReason is not null)
|
||||||
{
|
{
|
||||||
var v = this.hideEasing.IsDone ? 0f : 1f - (float)this.hideEasing.Value;
|
var v = this.hideEasing.IsDone || ReducedMotions ? 0f : 1f - (float)this.hideEasing.Value;
|
||||||
var midpoint = (this.prevProgressL + this.prevProgressR) / 2f;
|
var midpoint = (this.prevProgressL + this.prevProgressR) / 2f;
|
||||||
var length = (this.prevProgressR - this.prevProgressL) / 2f;
|
var length = (this.prevProgressR - this.prevProgressL) / 2f;
|
||||||
barL = midpoint - (length * v);
|
barL = midpoint - (length * v);
|
||||||
|
|
@ -455,7 +555,7 @@ internal sealed partial class ActiveNotification
|
||||||
this.prevProgressL = barL;
|
this.prevProgressL = barL;
|
||||||
this.prevProgressR = barR;
|
this.prevProgressR = barR;
|
||||||
}
|
}
|
||||||
else if (effectiveExpiry == DateTime.MaxValue)
|
else if (this.EffectiveExpiry == DateTime.MaxValue)
|
||||||
{
|
{
|
||||||
if (this.ShowIndeterminateIfNoExpiry)
|
if (this.ShowIndeterminateIfNoExpiry)
|
||||||
{
|
{
|
||||||
|
|
@ -477,8 +577,8 @@ internal sealed partial class ActiveNotification
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
barL = 1f - (float)((effectiveExpiry - DateTime.Now).TotalMilliseconds /
|
barL = 1f - (float)((this.EffectiveExpiry - DateTime.Now).TotalMilliseconds /
|
||||||
(effectiveExpiry - this.lastInterestTime).TotalMilliseconds);
|
(this.EffectiveExpiry - this.lastInterestTime).TotalMilliseconds);
|
||||||
barR = 1f;
|
barR = 1f;
|
||||||
this.prevProgressL = barL;
|
this.prevProgressL = barL;
|
||||||
this.prevProgressR = barR;
|
this.prevProgressR = barR;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System.Runtime.Loader;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Interface.Animation;
|
using Dalamud.Interface.Animation;
|
||||||
using Dalamud.Interface.Animation.EasingFunctions;
|
using Dalamud.Interface.Animation.EasingFunctions;
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.Internal;
|
||||||
|
|
@ -187,16 +188,18 @@ internal sealed partial class ActiveNotification : IActiveNotification
|
||||||
set => this.newProgress = value;
|
set => this.newProgress = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool ReducedMotions => Service<DalamudConfiguration>.Get().ReduceMotions;
|
||||||
|
|
||||||
/// <summary>Gets the eased progress.</summary>
|
/// <summary>Gets the eased progress.</summary>
|
||||||
private float ProgressEased
|
private float ProgressEased
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var underlyingProgress = this.underlyingNotification.Progress;
|
var underlyingProgress = this.underlyingNotification.Progress;
|
||||||
if (Math.Abs(underlyingProgress - this.progressBefore) < 0.000001f || this.progressEasing.IsDone)
|
if (Math.Abs(underlyingProgress - this.progressBefore) < 0.000001f || this.progressEasing.IsDone || ReducedMotions)
|
||||||
return underlyingProgress;
|
return underlyingProgress;
|
||||||
|
|
||||||
var state = Math.Clamp((float)this.progressEasing.Value, 0f, 1f);
|
var state = ReducedMotions ? 1f : Math.Clamp((float)this.progressEasing.Value, 0f, 1f);
|
||||||
return this.progressBefore + (state * (underlyingProgress - this.progressBefore));
|
return this.progressBefore + (state * (underlyingProgress - this.progressBefore));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,10 @@ internal static class NotificationConstants
|
||||||
/// <summary>The duration of indeterminate progress bar loop in milliseconds.</summary>
|
/// <summary>The duration of indeterminate progress bar loop in milliseconds.</summary>
|
||||||
public const float IndeterminateProgressbarLoopDuration = 2000f;
|
public const float IndeterminateProgressbarLoopDuration = 2000f;
|
||||||
|
|
||||||
|
/// <summary>The duration of indeterminate pie loop in milliseconds.</summary>
|
||||||
|
/// <remarks>Note that this value is applicable when reduced motion configuration is on.</remarks>
|
||||||
|
public const float IndeterminatePieLoopDuration = 8000f;
|
||||||
|
|
||||||
/// <summary>The duration of the progress wave animation in milliseconds.</summary>
|
/// <summary>The duration of the progress wave animation in milliseconds.</summary>
|
||||||
public const float ProgressWaveLoopDuration = 2000f;
|
public const float ProgressWaveLoopDuration = 2000f;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,12 @@ public class SettingsTabLook : SettingsTab
|
||||||
Loc.Localize("DalamudSettingInstallerOpenDefaultHint", "This will allow you to open the Plugin Installer to the \"Installed Plugins\" tab by default, instead of the \"Available Plugins\" tab."),
|
Loc.Localize("DalamudSettingInstallerOpenDefaultHint", "This will allow you to open the Plugin Installer to the \"Installed Plugins\" tab by default, instead of the \"Available Plugins\" tab."),
|
||||||
c => c.PluginInstallerOpen == PluginInstallerWindow.PluginInstallerOpenKind.InstalledPlugins,
|
c => c.PluginInstallerOpen == PluginInstallerWindow.PluginInstallerOpenKind.InstalledPlugins,
|
||||||
(v, c) => c.PluginInstallerOpen = v ? PluginInstallerWindow.PluginInstallerOpenKind.InstalledPlugins : PluginInstallerWindow.PluginInstallerOpenKind.AllPlugins),
|
(v, c) => c.PluginInstallerOpen = v ? PluginInstallerWindow.PluginInstallerOpenKind.InstalledPlugins : PluginInstallerWindow.PluginInstallerOpenKind.AllPlugins),
|
||||||
|
|
||||||
|
new SettingsEntry<bool>(
|
||||||
|
Loc.Localize("DalamudSettingReducedMotion", "Reduce motions"),
|
||||||
|
Loc.Localize("DalamudSettingReducedMotion", "This will suppress certain animations from Dalamud, such as the notification popup."),
|
||||||
|
c => c.ReduceMotions,
|
||||||
|
(v, c) => c.ReduceMotions = v),
|
||||||
};
|
};
|
||||||
|
|
||||||
public override string Title => Loc.Localize("DalamudSettingsVisual", "Look & Feel");
|
public override string Title => Loc.Localize("DalamudSettingsVisual", "Look & Feel");
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,9 @@ public static class DateTimeSpanExtensions
|
||||||
|
|
||||||
/// <summary>Formats an instance of <see cref="DateTime"/> as a localized relative time.</summary>
|
/// <summary>Formats an instance of <see cref="DateTime"/> as a localized relative time.</summary>
|
||||||
/// <param name="when">When.</param>
|
/// <param name="when">When.</param>
|
||||||
|
/// <param name="floorBy">The alignment unit of time span.</param>
|
||||||
/// <returns>The formatted string.</returns>
|
/// <returns>The formatted string.</returns>
|
||||||
public static string LocRelativePastLong(this DateTime when)
|
public static string LocRelativePastLong(this DateTime when, TimeSpan floorBy)
|
||||||
{
|
{
|
||||||
var loc = Loc.Localize(
|
var loc = Loc.Localize(
|
||||||
"DateTimeSpanExtensions.RelativeFormatStringsLong",
|
"DateTimeSpanExtensions.RelativeFormatStringsLong",
|
||||||
|
|
@ -55,13 +56,17 @@ public static class DateTimeSpanExtensions
|
||||||
if (relativeFormatStringLong?.FormatStringLoc != loc)
|
if (relativeFormatStringLong?.FormatStringLoc != loc)
|
||||||
relativeFormatStringLong ??= new(loc);
|
relativeFormatStringLong ??= new(loc);
|
||||||
|
|
||||||
return relativeFormatStringLong.Format(DateTime.Now - when);
|
return
|
||||||
|
floorBy == default
|
||||||
|
? relativeFormatStringLong.Format(DateTime.Now - when)
|
||||||
|
: relativeFormatStringLong.Format(Math.Floor((DateTime.Now - when) / floorBy) * floorBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Formats an instance of <see cref="DateTime"/> as a localized relative time.</summary>
|
/// <summary>Formats an instance of <see cref="DateTime"/> as a localized relative time.</summary>
|
||||||
/// <param name="when">When.</param>
|
/// <param name="when">When.</param>
|
||||||
|
/// <param name="floorBy">The alignment unit of time span.</param>
|
||||||
/// <returns>The formatted string.</returns>
|
/// <returns>The formatted string.</returns>
|
||||||
public static string LocRelativePastShort(this DateTime when)
|
public static string LocRelativePastShort(this DateTime when, TimeSpan floorBy)
|
||||||
{
|
{
|
||||||
var loc = Loc.Localize(
|
var loc = Loc.Localize(
|
||||||
"DateTimeSpanExtensions.RelativeFormatStringsShort",
|
"DateTimeSpanExtensions.RelativeFormatStringsShort",
|
||||||
|
|
@ -71,9 +76,22 @@ public static class DateTimeSpanExtensions
|
||||||
if (relativeFormatStringShort?.FormatStringLoc != loc)
|
if (relativeFormatStringShort?.FormatStringLoc != loc)
|
||||||
relativeFormatStringShort = new(loc);
|
relativeFormatStringShort = new(loc);
|
||||||
|
|
||||||
return relativeFormatStringShort.Format(DateTime.Now - when);
|
return
|
||||||
|
floorBy == default
|
||||||
|
? relativeFormatStringShort.Format(DateTime.Now - when)
|
||||||
|
: relativeFormatStringShort.Format(Math.Floor((DateTime.Now - when) / floorBy) * floorBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Formats an instance of <see cref="DateTime"/> as a localized relative time.</summary>
|
||||||
|
/// <param name="when">When.</param>
|
||||||
|
/// <returns>The formatted string.</returns>
|
||||||
|
public static string LocRelativePastLong(this DateTime when) => when.LocRelativePastLong(TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
|
/// <summary>Formats an instance of <see cref="DateTime"/> as a localized relative time.</summary>
|
||||||
|
/// <param name="when">When.</param>
|
||||||
|
/// <returns>The formatted string.</returns>
|
||||||
|
public static string LocRelativePastShort(this DateTime when) => when.LocRelativePastShort(TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
private sealed class ParsedRelativeFormatStrings
|
private sealed class ParsedRelativeFormatStrings
|
||||||
{
|
{
|
||||||
private readonly List<(float MinSeconds, string FormatString)> formatStrings = new();
|
private readonly List<(float MinSeconds, string FormatString)> formatStrings = new();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue