Force SHA1 hashing on updated hash files

This commit is contained in:
cake
2025-12-02 06:33:08 +01:00
parent 481bc99dcd
commit 72cd5006db
7 changed files with 214 additions and 74 deletions

View File

@@ -449,13 +449,12 @@ public sealed class FileCacheManager : IHostedService
_logger.LogTrace("Updating hash for {path}", fileCache.ResolvedFilepath);
var oldHash = fileCache.Hash;
var prefixedPath = fileCache.PrefixedFilePath;
var algo = Crypto.DetectAlgo(fileCache.ResolvedFilepath);
if (computeProperties)
{
var fi = new FileInfo(fileCache.ResolvedFilepath);
fileCache.Size = fi.Length;
fileCache.CompressedSize = null;
fileCache.Hash = Crypto.ComputeFileHash(fileCache.ResolvedFilepath, algo);
fileCache.Hash = Crypto.ComputeFileHash(fileCache.ResolvedFilepath, Crypto.HashAlgo.Sha1);
fileCache.LastModifiedDateTicks = fi.LastWriteTimeUtc.Ticks.ToString(CultureInfo.InvariantCulture);
}
RemoveHashedFile(oldHash, prefixedPath);

View File

@@ -65,6 +65,7 @@ public class LightlessConfig : ILightlessConfiguration
public bool ShowOnlineNotificationsOnlyForNamedPairs { get; set; } = false;
public bool ShowTransferBars { get; set; } = true;
public bool ShowTransferWindow { get; set; } = false;
public bool ShowPlayerLinesTransferWindow { get; set; } = true;
public bool UseNotificationsForDownloads { get; set; } = true;
public bool ShowUploading { get; set; } = true;
public bool ShowUploadingBigText { get; set; } = true;

View File

@@ -24,15 +24,9 @@ public class DownloadUi : WindowMediatorSubscriberBase
private readonly PairProcessingLimiter _pairProcessingLimiter;
private readonly ConcurrentDictionary<GameObjectHandler, bool> _uploadingPlayers = new();
private readonly Dictionary<GameObjectHandler, Vector2> _smoothed = [];
private readonly Dictionary<GameObjectHandler, DownloadSpeedTracker> _downloadSpeeds = new();
private sealed class DownloadSpeedTracker
{
public long LastBytes;
public double LastTime;
public double SpeedBytesPerSecond;
}
private readonly Dictionary<GameObjectHandler, DownloadSpeedTracker> _downloadSpeeds = [];
private byte _transferBoxTransparency = 100;
private bool _notificationDismissed = true;
private int _lastDownloadStateHash = 0;
@@ -160,7 +154,6 @@ public class DownloadUi : WindowMediatorSubscriberBase
if (_configService.Current.ShowTransferBars)
{
const int transparency = 100;
const int dlBarBorder = 3;
const float rounding = 6f;
var shadowOffset = new Vector2(2, 2);
@@ -210,10 +203,10 @@ public class DownloadUi : WindowMediatorSubscriberBase
var drawList = ImGui.GetBackgroundDrawList();
//Shadow, background, border, bar background
drawList.AddRectFilled(outerStart + shadowOffset, outerEnd + shadowOffset, UiSharedService.Color(0, 0, 0, transparency / 2), rounding + 2);
drawList.AddRectFilled(outerStart, outerEnd, UiSharedService.Color(0, 0, 0, transparency), rounding + 2);
drawList.AddRectFilled(outerStart + shadowOffset, outerEnd + shadowOffset, UiSharedService.Color(0, 0, 0, 100 / 2), rounding + 2);
drawList.AddRectFilled(outerStart, outerEnd, UiSharedService.Color(0, 0, 0, 100), rounding + 2);
drawList.AddRectFilled(borderStart, borderEnd, UiSharedService.Color(ImGuiColors.DalamudGrey), rounding);
drawList.AddRectFilled(dlBarStart, dlBarEnd, UiSharedService.Color(0, 0, 0, transparency), rounding);
drawList.AddRectFilled(dlBarStart, dlBarEnd, UiSharedService.Color(0, 0, 0, 100), rounding);
var dlProgressPercent = transferredBytes / (double)totalBytes;
var progressEndX = dlBarStart.X + (float)(dlProgressPercent * dlBarWidth);
@@ -226,7 +219,7 @@ public class DownloadUi : WindowMediatorSubscriberBase
var downloadText = $"{UiSharedService.ByteToString(transferredBytes, addSuffix: false)}/{UiSharedService.ByteToString(totalBytes)}";
UiSharedService.DrawOutlinedFont(drawList, downloadText, screenPos with { X = screenPos.X - textSize.X / 2f - 1, Y = screenPos.Y - textSize.Y / 2f - 1 },
UiSharedService.Color(ImGuiColors.DalamudGrey),
UiSharedService.Color(0, 0, 0, transparency),
UiSharedService.Color(0, 0, 0, 100),
1
);
}
@@ -249,7 +242,7 @@ public class DownloadUi : WindowMediatorSubscriberBase
var drawList = ImGui.GetBackgroundDrawList();
UiSharedService.DrawOutlinedFont(drawList, uploadText, screenPos with { X = screenPos.X - textSize.X / 2f - 1, Y = screenPos.Y - textSize.Y / 2f - 1 },
UiSharedService.Color(ImGuiColors.DalamudYellow),
UiSharedService.Color(0, 0, 0, transparency),
UiSharedService.Color(0, 0, 0, 100),
2
);
}
@@ -267,7 +260,6 @@ public class DownloadUi : WindowMediatorSubscriberBase
if (!_currentDownloads.Any())
return;
const int transparency = 150;
const float padding = 6f;
const float spacingY = 2f;
const float minBoxWidth = 320f;
@@ -279,6 +271,7 @@ public class DownloadUi : WindowMediatorSubscriberBase
long totalBytes = 0;
long transferredBytes = 0;
// (Name, files done, files total, bytes done, bytes total, speed)
var perPlayer = new List<(string Name, int TransferredFiles, int TotalFiles, long TransferredBytes, long TotalBytes, double SpeedBytesPerSecond)>();
foreach (var transfer in _currentDownloads.ToList())
@@ -301,29 +294,11 @@ public class DownloadUi : WindowMediatorSubscriberBase
{
if (!_downloadSpeeds.TryGetValue(handler, out var tracker))
{
tracker = new DownloadSpeedTracker
{
LastBytes = playerTransferredBytes,
LastTime = now,
SpeedBytesPerSecond = 0
};
tracker = new DownloadSpeedTracker(windowSeconds: 3.0);
_downloadSpeeds[handler] = tracker;
}
var dt = now - tracker.LastTime;
var dBytes = playerTransferredBytes - tracker.LastBytes;
if (dt > 0.1 && dBytes >= 0)
{
var instant = dBytes / dt;
tracker.SpeedBytesPerSecond = tracker.SpeedBytesPerSecond <= 0
? instant
: tracker.SpeedBytesPerSecond * 0.8 + instant * 0.2;
}
tracker.LastTime = now;
tracker.LastBytes = playerTransferredBytes;
speed = tracker.SpeedBytesPerSecond;
speed = tracker.Update(now, playerTransferredBytes);
}
perPlayer.Add((
@@ -336,6 +311,7 @@ public class DownloadUi : WindowMediatorSubscriberBase
));
}
// Clean speed trackers for players with no active downloads
foreach (var handler in _downloadSpeeds.Keys.ToList())
{
if (!_currentDownloads.ContainsKey(handler))
@@ -345,24 +321,30 @@ public class DownloadUi : WindowMediatorSubscriberBase
if (totalFiles == 0 || totalBytes == 0)
return;
// max speed for scale (clamped)
double maxSpeed = perPlayer.Count > 0 ? perPlayer.Max(p => p.SpeedBytesPerSecond) : 0;
if (maxSpeed <= 0)
maxSpeed = 1;
var drawList = ImGui.GetBackgroundDrawList();
var windowPos = ImGui.GetWindowPos();
// Overall texts
var headerText = $"Downloading {transferredFiles}/{totalFiles} files";
var bytesText = $"{UiSharedService.ByteToString(transferredBytes, addSuffix: false)}/{UiSharedService.ByteToString(totalBytes)}";
var totalSpeed = perPlayer.Sum(p => p.SpeedBytesPerSecond);
var speedText = totalSpeed > 0
? $"{UiSharedService.ByteToString((long)totalSpeed)}/s"
: "Calculating lightspeed...";
: "Calculating in lightspeed...";
var headerSize = ImGui.CalcTextSize(headerText);
var bytesSize = ImGui.CalcTextSize(bytesText);
var speedSize = ImGui.CalcTextSize(speedText);
var totalSpeedSize = ImGui.CalcTextSize(speedText);
float contentWidth = headerSize.X;
if (bytesSize.X > contentWidth) contentWidth = bytesSize.X;
if (speedSize.X > contentWidth) contentWidth = speedSize.X;
if (totalSpeedSize.X > contentWidth) contentWidth = totalSpeedSize.X;
foreach (var p in perPlayer)
{
@@ -379,60 +361,114 @@ public class DownloadUi : WindowMediatorSubscriberBase
contentWidth = lineSize.X;
}
var boxWidth = contentWidth + padding * 2;
var lineHeight = ImGui.GetTextLineHeight();
var globalBarHeight = lineHeight * 0.8f;
var perPlayerBarHeight = lineHeight * 0.4f;
// Box width
float boxWidth = contentWidth + padding * 2;
if (boxWidth < minBoxWidth)
boxWidth = minBoxWidth;
var lineHeight = ImGui.GetTextLineHeight();
var numTextLines = 3 + perPlayer.Count;
var barHeight = lineHeight * 0.8f;
var boxHeight = padding * 3 + barHeight + numTextLines * (lineHeight + spacingY);
float boxHeight = 0;
boxHeight += padding;
boxHeight += globalBarHeight;
boxHeight += padding;
var origin = windowPos;
boxHeight += lineHeight + spacingY;
boxHeight += lineHeight + spacingY;
boxHeight += lineHeight * 1.4f + spacingY;
var boxMin = origin;
var boxMax = origin + new Vector2(boxWidth, boxHeight);
boxHeight += perPlayer.Count * (lineHeight + perPlayerBarHeight + spacingY * 2);
boxHeight += padding;
drawList.AddRectFilled(boxMin, boxMax, UiSharedService.Color(0, 0, 0, transparency), 5f);
var boxMin = windowPos;
var boxMax = new Vector2(windowPos.X + boxWidth, windowPos.Y + boxHeight);
// Background + border
drawList.AddRectFilled(boxMin, boxMax, UiSharedService.Color(0, 0, 0, _transferBoxTransparency), 5f);
drawList.AddRect(boxMin, boxMax, UiSharedService.Color(ImGuiColors.DalamudGrey), 5f);
// Progress bar
var cursor = boxMin + new Vector2(padding, padding);
var barMin = cursor;
var barMax = new Vector2(boxMin.X + boxWidth - padding, cursor.Y + barHeight);
var barMax = new Vector2(boxMin.X + boxWidth - padding, cursor.Y + globalBarHeight);
var progress = (float)transferredBytes / totalBytes;
drawList.AddRectFilled(barMin, barMax, UiSharedService.Color(40, 40, 40, transparency), 3f);
if (progress < 0f) progress = 0f;
if (progress > 1f) progress = 1f;
drawList.AddRectFilled(barMin, barMax, UiSharedService.Color(40, 40, 40, _transferBoxTransparency), 3f);
drawList.AddRectFilled(barMin, new Vector2(barMin.X + (barMax.X - barMin.X) * progress, barMax.Y), UiSharedService.Color(UIColors.Get("LightlessPurple")), 3f);
cursor.Y = barMax.Y + padding;
// Header
UiSharedService.DrawOutlinedFont(drawList, headerText, cursor, UiSharedService.Color(ImGuiColors.DalamudWhite), UiSharedService.Color(0, 0, 0, transparency), 1);
UiSharedService.DrawOutlinedFont(drawList, headerText, cursor, UiSharedService.Color(ImGuiColors.DalamudWhite), UiSharedService.Color(0, 0, 0, _transferBoxTransparency), 1);
cursor.Y += lineHeight + spacingY;
// Bytes
UiSharedService.DrawOutlinedFont(drawList, bytesText, cursor, UiSharedService.Color(ImGuiColors.DalamudWhite), UiSharedService.Color(0, 0, 0, transparency), 1);
UiSharedService.DrawOutlinedFont(drawList, bytesText, cursor, UiSharedService.Color(ImGuiColors.DalamudWhite), UiSharedService.Color(0, 0, 0, _transferBoxTransparency), 1);
cursor.Y += lineHeight + spacingY;
// Total speed WIP
UiSharedService.DrawOutlinedFont(drawList, speedText, cursor, UiSharedService.Color(UIColors.Get("LightlessPurple")), UiSharedService.Color(0, 0, 0, transparency), 1);
cursor.Y += lineHeight * 1.4f;
UiSharedService.DrawOutlinedFont(drawList, speedText, cursor, UiSharedService.Color(UIColors.Get("LightlessPurple")), UiSharedService.Color(0, 0, 0, _transferBoxTransparency), 1);
cursor.Y += lineHeight * 1.4f + spacingY;
// Per-player lines
foreach (var p in perPlayer.OrderByDescending(p => p.TotalBytes))
if (_configService.Current.ShowPlayerLinesTransferWindow)
{
var playerSpeedText = p.SpeedBytesPerSecond > 0
? $"{UiSharedService.ByteToString((long)p.SpeedBytesPerSecond)}/s"
: "-";
// Per-player lines
var orderedPlayers = perPlayer.OrderByDescending(p => p.TotalBytes).ToList();
var line = $"{p.Name}: {p.TransferredFiles}/{p.TotalFiles} " +
$"({UiSharedService.ByteToString(p.TransferredBytes, addSuffix: false)}/{UiSharedService.ByteToString(p.TotalBytes)}) " +
$"@ {playerSpeedText}";
foreach (var p in orderedPlayers)
{
var playerSpeedText = p.SpeedBytesPerSecond > 0
? $"{UiSharedService.ByteToString((long)p.SpeedBytesPerSecond)}/s"
: "-";
UiSharedService.DrawOutlinedFont(drawList, line, cursor, UiSharedService.Color(ImGuiColors.DalamudWhite), UiSharedService.Color(0, 0, 0, transparency), 1);
var line = $"{p.Name}: {p.TransferredFiles}/{p.TotalFiles} " +
$"({UiSharedService.ByteToString(p.TransferredBytes, addSuffix: false)}/{UiSharedService.ByteToString(p.TotalBytes)}) " +
$"@ {playerSpeedText}";
cursor.Y += lineHeight + spacingY;
UiSharedService.DrawOutlinedFont(
drawList,
line,
cursor,
UiSharedService.Color(255, 255, 255, _transferBoxTransparency),
UiSharedService.Color(0, 0, 0, _transferBoxTransparency),
1
);
cursor.Y += lineHeight + spacingY;
var barBgMin = new Vector2(boxMin.X + padding, cursor.Y);
var barBgMax = new Vector2(boxMax.X - padding, cursor.Y + perPlayerBarHeight);
drawList.AddRectFilled(
barBgMin,
barBgMax,
UiSharedService.Color(40, 40, 40, _transferBoxTransparency),
3f
);
float ratio = 0f;
if (maxSpeed > 0)
ratio = (float)(p.SpeedBytesPerSecond / maxSpeed);
if (ratio < 0f) ratio = 0f;
if (ratio > 1f) ratio = 1f;
var fillX = barBgMin.X + (barBgMax.X - barBgMin.X) * ratio;
var barFillMax = new Vector2(fillX, barBgMax.Y);
drawList.AddRectFilled(
barBgMin,
barFillMax,
UiSharedService.Color(UIColors.Get("LightlessPurple")),
3f
);
cursor.Y += perPlayerBarHeight + spacingY * 2;
}
}
}
@@ -534,4 +570,70 @@ public class DownloadUi : WindowMediatorSubscriberBase
}
}
}
private sealed class DownloadSpeedTracker
{
private readonly Queue<(double Time, long Bytes)> _samples = new();
private readonly double _windowSeconds;
public double SpeedBytesPerSecond { get; private set; }
public DownloadSpeedTracker(double windowSeconds = 3.0)
{
_windowSeconds = windowSeconds;
}
public double Update(double now, long totalBytes)
{
if (_samples.Count > 0 && totalBytes < _samples.Last().Bytes)
{
_samples.Clear();
}
_samples.Enqueue((now, totalBytes));
while (_samples.Count > 0 && now - _samples.Peek().Time > _windowSeconds)
_samples.Dequeue();
if (_samples.Count < 2)
{
SpeedBytesPerSecond = 0;
return SpeedBytesPerSecond;
}
var oldest = _samples.Peek();
var newest = _samples.Last();
var dt = newest.Time - oldest.Time;
if (dt <= 0.0001)
{
SpeedBytesPerSecond = 0;
return SpeedBytesPerSecond;
}
var dBytes = newest.Bytes - oldest.Bytes;
if (dBytes <= 0)
{
SpeedBytesPerSecond = 0;
return SpeedBytesPerSecond;
}
const long minBytesForSpeed = 32 * 1024;
if (dBytes < minBytesForSpeed)
{
return SpeedBytesPerSecond;
}
var avg = dBytes / dt;
const double alpha = 0.3;
SpeedBytesPerSecond = SpeedBytesPerSecond <= 0
? avg
: SpeedBytesPerSecond * (1 - alpha) + avg * alpha;
return SpeedBytesPerSecond;
}
}
}

View File

@@ -348,7 +348,7 @@ public sealed class DtrEntry : IDisposable, IHostedService
try
{
var cid = _dalamudUtilService.GetCIDAsync().GetAwaiter().GetResult();
var hashedCid = cid.ToString().GetBlake3Hash();
var hashedCid = cid.ToString().GetHash256();
_localHashedCid = hashedCid;
_localHashedCidFetchedAt = now;
return hashedCid;

View File

@@ -434,8 +434,10 @@ public partial class EditProfileUi
try
{
var fileContent = await File.ReadAllBytesAsync(filePath).ConfigureAwait(false);
await using var stream = new MemoryStream(fileContent);
var format = await Image.DetectFormatAsync(stream).ConfigureAwait(false);
var stream = new MemoryStream(fileContent);
await using (stream.ConfigureAwait(false))
{
var format = await Image.DetectFormatAsync(stream).ConfigureAwait(false);
if (!IsSupportedImageFormat(format))
{
_showProfileImageError = true;
@@ -461,6 +463,7 @@ public partial class EditProfileUi
_showProfileImageError = false;
_queuedProfileImage = fileContent;
Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
}
}
catch (Exception ex)
{

View File

@@ -818,11 +818,19 @@ public class SettingsUi : WindowMediatorSubscriberBase
$"D = Decompressing download");
if (!_configService.Current.ShowTransferWindow) ImGui.BeginDisabled();
ImGui.Indent();
bool editTransferWindowPosition = _uiShared.EditTrackerPosition;
if (ImGui.Checkbox("Edit Transfer Window position", ref editTransferWindowPosition))
{
_uiShared.EditTrackerPosition = editTransferWindowPosition;
}
bool showPlayerLinesTransferWindow = _configService.Current.ShowPlayerLinesTransferWindow;
if (ImGui.Checkbox("Toggle the Player Lines in the Transfer Window", ref showPlayerLinesTransferWindow))
{
_configService.Current.ShowPlayerLinesTransferWindow = showPlayerLinesTransferWindow;
_configService.Save();
}
ImGui.Unindent();
if (!_configService.Current.ShowTransferWindow) ImGui.EndDisabled();

View File

@@ -37,7 +37,7 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase
private GroupJoinDto? _joinDto;
private GroupJoinInfoDto? _joinInfo;
private DefaultPermissionsDto _ownPermissions = null!;
private const bool _useTestSyncshells = false;
private bool _useTestSyncshells = false;
private bool _compactView = false;
@@ -82,7 +82,15 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase
{
ImGui.BeginGroup();
_uiSharedService.MediumText("Nearby Syncshells", UIColors.Get("LightlessPurple"));
#if DEBUG
if (ImGui.SmallButton("Show test syncshells"))
{
_useTestSyncshells = !_useTestSyncshells;
_ = Task.Run(async () => await RefreshSyncshellsAsync().ConfigureAwait(false));
}
ImGui.SameLine();
#endif
string checkboxLabel = "Compact view";
float availWidth = ImGui.GetContentRegionAvail().X;
@@ -274,11 +282,30 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase
? shell.Group.Alias
: shell.Group.GID;
_uiSharedService.MediumText(displayName, UIColors.Get("LightlessPurple"));
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"));
float startX = ImGui.GetCursorPosX();
float availWidth = ImGui.GetContentRegionAvail().X;
float rightTextW = ImGui.CalcTextSize(broadcasterName).X;
ImGui.TextColored(ImGuiColors.DalamudGrey, "Broadcaster");
ImGui.BeginGroup();
_uiSharedService.MediumText(displayName, UIColors.Get("LightlessPurple"));
if (ImGui.IsItemHovered())
ImGui.SetTooltip("Click to open profile.");
if (ImGui.IsItemClicked())
{
//open profile of syncshell
}
ImGui.SameLine();
float rightX = startX + availWidth - rightTextW;
var pos = ImGui.GetCursorPos();
ImGui.SetCursorPos(new Vector2(rightX, pos.Y + 3f * ImGuiHelpers.GlobalScale));
ImGui.TextUnformatted(broadcasterName);
if (ImGui.IsItemHovered())
ImGui.SetTooltip("Broadcaster of the syncshell.");
ImGui.EndGroup();
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"));
ImGui.Dummy(new Vector2(0, 6 * ImGuiHelpers.GlobalScale));
@@ -539,7 +566,7 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase
ClearSelection();
}
private List<GroupJoinDto> BuildTestSyncshells()
private static List<GroupJoinDto> BuildTestSyncshells()
{
var testGroup1 = new GroupData("TEST-ALPHA", "Alpha Shell");
var testGroup2 = new GroupData("TEST-BETA", "Beta Shell");