Files
ClubPenguinClient/MareSynchronos/UI/DownloadUi.cs
rootdarkarchon 0c87e84f25 [Draft] Update 0.8 (#46)
* move stuff out into file transfer manager

* obnoxious unsupported version text, adjustments to filetransfermanager

* add back file upload transfer progress

* restructure code

* cleanup some more stuff I guess

* downloadids by playername

* individual anim/sound bs

* fix migration stuff, finalize impl of individual sound/anim pause

* fixes with logging stuff

* move download manager to transient

* rework dl ui first iteration

* some refactoring and cleanup

* more code cleanup

* refactoring

* switch to hostbuilder

* some more rework I guess

* more refactoring

* clean up mediator calls and disposal

* fun code cleanup

* push error message when log level is set to anything but information in non-debug builds

* remove notificationservice

* move message to after login

* add download bars to gameworld

* fixes download progress bar

* set gpose ui min and max size

* remove unnecessary usings

* adjustments to reconnection logic

* add options to set visible/offline groups visibility

* add impl of uploading display, transfer list in settings ui

* attempt to fix issues with server selection

* add back download status to compact ui

* make dl bar fixed size based

* some fixes for upload/download handling

* adjust text from Syncing back to Uploading

---------

Co-authored-by: rootdarkarchon <root.darkarchon@outlook.com>
Co-authored-by: Stanley Dimant <stanley.dimant@varian.com>
2023-03-14 19:48:35 +01:00

240 lines
11 KiB
C#

using Dalamud.Interface.Colors;
using ImGuiNET;
using MareSynchronos.MareConfiguration;
using MareSynchronos.PlayerData.Handlers;
using MareSynchronos.Services;
using MareSynchronos.Services.Mediator;
using MareSynchronos.WebAPI.Files;
using MareSynchronos.WebAPI.Files.Models;
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
using System.Numerics;
namespace MareSynchronos.UI;
public class DownloadUi : WindowMediatorSubscriberBase
{
private readonly MareConfigService _configService;
private readonly ConcurrentDictionary<GameObjectHandler, Dictionary<string, FileDownloadStatus>> _currentDownloads = new();
private readonly DalamudUtilService _dalamudUtilService;
private readonly FileUploadManager _fileTransferManager;
private readonly UiSharedService _uiShared;
private readonly ConcurrentDictionary<GameObjectHandler, bool> _uploadingPlayers = new();
public DownloadUi(ILogger<DownloadUi> logger, DalamudUtilService dalamudUtilService, MareConfigService configService,
FileUploadManager fileTransferManager, MareMediator mediator, UiSharedService uiShared) : base(logger, mediator, "Mare Synchronos Downloads")
{
_dalamudUtilService = dalamudUtilService;
_configService = configService;
_fileTransferManager = fileTransferManager;
_uiShared = uiShared;
SizeConstraints = new WindowSizeConstraints()
{
MaximumSize = new Vector2(500, 90),
MinimumSize = new Vector2(500, 90),
};
Flags |= ImGuiWindowFlags.NoMove;
Flags |= ImGuiWindowFlags.NoBackground;
Flags |= ImGuiWindowFlags.NoInputs;
Flags |= ImGuiWindowFlags.NoNavFocus;
Flags |= ImGuiWindowFlags.NoResize;
Flags |= ImGuiWindowFlags.NoScrollbar;
Flags |= ImGuiWindowFlags.NoTitleBar;
Flags |= ImGuiWindowFlags.NoDecoration;
ForceMainWindow = true;
IsOpen = true;
Mediator.Subscribe<DownloadStartedMessage>(this, (msg) => _currentDownloads[msg.DownloadId] = msg.DownloadStatus);
Mediator.Subscribe<DownloadFinishedMessage>(this, (msg) => _currentDownloads.TryRemove(msg.DownloadId, out _));
Mediator.Subscribe<GposeStartMessage>(this, (_) => IsOpen = false);
Mediator.Subscribe<GposeEndMessage>(this, (_) => IsOpen = true);
Mediator.Subscribe<PlayerUploadingMessage>(this, (msg) =>
{
if (msg.IsUploading)
{
_uploadingPlayers[msg.Handler] = true;
}
else
{
_uploadingPlayers.TryRemove(msg.Handler, out _);
}
});
}
public override void Draw()
{
if (!_configService.Current.ShowTransferWindow && !_configService.Current.ShowTransferBars) return;
if (!_currentDownloads.Any() && !_fileTransferManager.CurrentUploads.Any() && !_uploadingPlayers.Any()) return;
if (!IsOpen) return;
if (_configService.Current.ShowTransferWindow)
{
try
{
if (_fileTransferManager.CurrentUploads.Any())
{
var currentUploads = _fileTransferManager.CurrentUploads.ToList();
var totalUploads = currentUploads.Count;
var doneUploads = currentUploads.Count(c => c.IsTransferred);
var totalUploaded = currentUploads.Sum(c => c.Transferred);
var totalToUpload = currentUploads.Sum(c => c.Total);
UiSharedService.DrawOutlinedFont($"▲", ImGuiColors.DalamudWhite, new Vector4(0, 0, 0, 255), 1);
ImGui.SameLine();
var xDistance = ImGui.GetCursorPosX();
UiSharedService.DrawOutlinedFont($"Compressing+Uploading {doneUploads}/{totalUploads}",
ImGuiColors.DalamudWhite, new Vector4(0, 0, 0, 255), 1);
ImGui.NewLine();
ImGui.SameLine(xDistance);
UiSharedService.DrawOutlinedFont(
$"{UiSharedService.ByteToString(totalUploaded, addSuffix: false)}/{UiSharedService.ByteToString(totalToUpload)}",
ImGuiColors.DalamudWhite, new Vector4(0, 0, 0, 255), 1);
if (_currentDownloads.Any()) ImGui.Separator();
}
}
catch
{
// ignore errors thrown from UI
}
try
{
foreach (var item in _currentDownloads.ToList())
{
var dlSlot = item.Value.Count(c => c.Value.DownloadStatus == DownloadStatus.WaitingForSlot);
var dlQueue = item.Value.Count(c => c.Value.DownloadStatus == DownloadStatus.WaitingForQueue);
var dlProg = item.Value.Count(c => c.Value.DownloadStatus == DownloadStatus.Downloading);
var dlDecomp = item.Value.Count(c => c.Value.DownloadStatus == DownloadStatus.Decompressing);
var totalFiles = item.Value.Sum(c => c.Value.TotalFiles);
var transferredFiles = item.Value.Sum(c => c.Value.TransferredFiles);
var totalBytes = item.Value.Sum(c => c.Value.TotalBytes);
var transferredBytes = item.Value.Sum(c => c.Value.TransferredBytes);
UiSharedService.DrawOutlinedFont($"▼", ImGuiColors.DalamudWhite, new Vector4(0, 0, 0, 255), 1);
ImGui.SameLine();
var xDistance = ImGui.GetCursorPosX();
UiSharedService.DrawOutlinedFont(
$"{item.Key.Name} [W:{dlSlot}/Q:{dlQueue}/P:{dlProg}/D:{dlDecomp}]",
ImGuiColors.DalamudWhite, new Vector4(0, 0, 0, 255), 1);
ImGui.NewLine();
ImGui.SameLine(xDistance);
UiSharedService.DrawOutlinedFont(
$"{transferredFiles}/{totalFiles} ({UiSharedService.ByteToString(transferredBytes, addSuffix: false)}/{UiSharedService.ByteToString(totalBytes)})",
ImGuiColors.DalamudWhite, new Vector4(0, 0, 0, 255), 1);
}
}
catch
{
// ignore errors thrown from UI
}
}
if (_configService.Current.ShowTransferBars)
{
const int transparency = 100;
const int dlBarBorder = 3;
foreach (var transfer in _currentDownloads.ToList())
{
var screenPos = _dalamudUtilService.WorldToScreen(transfer.Key.GameObjectLazy.Value);
if (screenPos == Vector2.Zero) continue;
var totalBytes = transfer.Value.Sum(c => c.Value.TotalBytes);
var transferredBytes = transfer.Value.Sum(c => c.Value.TransferredBytes);
var downloadText =
$"{UiSharedService.ByteToString(transferredBytes, addSuffix: false)}/{UiSharedService.ByteToString(totalBytes)}";
var maxDlText = $"{UiSharedService.ByteToString(totalBytes, addSuffix: false)}/{UiSharedService.ByteToString(totalBytes)}";
var textSize = ImGui.CalcTextSize(maxDlText);
int dlBarHeight = (int)textSize.Y + 8;
int dlBarWidth = (int)textSize.X + 150;
var dlBarStart = new Vector2(screenPos.X - dlBarWidth / 2f, screenPos.Y - dlBarHeight / 2f);
var dlBarEnd = new Vector2(screenPos.X + dlBarWidth / 2f, screenPos.Y + dlBarHeight / 2f);
var drawList = ImGui.GetBackgroundDrawList();
drawList.AddRectFilled(
dlBarStart with { X = dlBarStart.X - dlBarBorder - 1, Y = dlBarStart.Y - dlBarBorder - 1 },
dlBarEnd with { X = dlBarEnd.X + dlBarBorder + 1, Y = dlBarEnd.Y + dlBarBorder + 1 },
UiSharedService.Color(0, 0, 0, transparency), 1);
drawList.AddRectFilled(dlBarStart with { X = dlBarStart.X - dlBarBorder, Y = dlBarStart.Y - dlBarBorder },
dlBarEnd with { X = dlBarEnd.X + dlBarBorder, Y = dlBarEnd.Y + dlBarBorder },
UiSharedService.Color(220, 220, 220, transparency), 1);
drawList.AddRectFilled(dlBarStart, dlBarEnd,
UiSharedService.Color(0, 0, 0, transparency), 1);
var dlProgressPercent = transferredBytes / (double)totalBytes;
drawList.AddRectFilled(dlBarStart,
dlBarEnd with { X = dlBarStart.X + (float)(dlProgressPercent * dlBarWidth) },
UiSharedService.Color(50, 205, 50, transparency), 1);
UiSharedService.DrawOutlinedFont(drawList, downloadText,
screenPos with { X = screenPos.X - textSize.X / 2f - 1, Y = screenPos.Y - textSize.Y / 2f - 1 },
UiSharedService.Color(255, 255, 255, transparency),
UiSharedService.Color(0, 0, 0, transparency), 1);
}
if (_configService.Current.ShowUploading)
{
foreach (var player in _uploadingPlayers.Select(p => p.Key).ToList())
{
var screenPos = _dalamudUtilService.WorldToScreen(player.GameObjectLazy.Value);
if (screenPos == Vector2.Zero) continue;
try
{
if (_uiShared.UidFontBuilt && _configService.Current.ShowUploadingBigText) ImGui.PushFont(_uiShared.UidFont);
var uploadText = "Uploading";
var textSize = ImGui.CalcTextSize(uploadText);
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(255, 255, 0, transparency),
UiSharedService.Color(0, 0, 0, transparency), 2);
}
catch
{
// ignore errors thrown on UI
}
finally
{
if (_uiShared.UidFontBuilt && _configService.Current.ShowUploadingBigText) ImGui.PopFont();
}
}
}
}
}
public override void PreDraw()
{
base.PreDraw();
if (_uiShared.EditTrackerPosition)
{
Flags &= ~ImGuiWindowFlags.NoMove;
Flags &= ~ImGuiWindowFlags.NoBackground;
Flags &= ~ImGuiWindowFlags.NoInputs;
Flags &= ~ImGuiWindowFlags.NoResize;
}
else
{
Flags |= ImGuiWindowFlags.NoMove;
Flags |= ImGuiWindowFlags.NoBackground;
Flags |= ImGuiWindowFlags.NoInputs;
Flags |= ImGuiWindowFlags.NoResize;
}
var maxHeight = ImGui.GetTextLineHeight() * (_configService.Current.ParallelDownloads + 3);
SizeConstraints = new()
{
MinimumSize = new Vector2(300, maxHeight),
MaximumSize = new Vector2(300, maxHeight),
};
}
}