add new main UI, up version

This commit is contained in:
Stanley Dimant
2022-07-08 01:35:09 +02:00
parent c604e5fa37
commit d5486307ee
8 changed files with 1117 additions and 782 deletions

View File

@@ -231,6 +231,7 @@ namespace MareSynchronos.Managers
|| f.EndsWith(".mdl", StringComparison.OrdinalIgnoreCase)
|| f.EndsWith(".mtrl", StringComparison.OrdinalIgnoreCase)))
.Concat(Directory.EnumerateFiles(_pluginConfiguration.CacheFolder, "*.*", SearchOption.AllDirectories)
.Where(f => new FileInfo(f).Name.Length == 40)
.Select(s => s.ToLowerInvariant()))
.Select(p => new KeyValuePair<string, bool>(p, false)).ToList());
List<FileCache> fileCaches;

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<Authors></Authors>
<Company></Company>
<Version>0.0.12.0</Version>
<Version>0.1.0.0</Version>
<Description></Description>
<Copyright></Copyright>
<PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl>

View File

@@ -28,13 +28,16 @@ namespace MareSynchronos
private readonly IntroUi _introUi;
private readonly IpcManager _ipcManager;
public static DalamudPluginInterface PluginInterface { get; set; }
private readonly MainUi _mainUi;
private readonly SettingsUi _settingsUi;
private readonly WindowSystem _windowSystem;
private PlayerManager? _playerManager;
private readonly DalamudUtil _dalamudUtil;
private OnlinePlayerManager? _characterCacheManager;
private readonly DownloadUi _downloadUi;
private readonly FileDialogManager _fileDialogManager;
private readonly CompactUi _compactUi;
private readonly UiShared _uiSharedComponent;
public Plugin(DalamudPluginInterface pluginInterface, CommandManager commandManager,
Framework framework, ObjectTable objectTable, ClientState clientState)
@@ -60,24 +63,30 @@ namespace MareSynchronos
_fileCacheManager = new FileCacheManager(_ipcManager, _configuration);
_fileDialogManager = new FileDialogManager();
var uiSharedComponent =
new UiShared(_ipcManager, _apiController, _fileCacheManager, _fileDialogManager, _configuration, _dalamudUtil);
_mainUi = new MainUi(_windowSystem, uiSharedComponent, _configuration, _apiController);
_uiSharedComponent =
new UiShared(_ipcManager, _apiController, _fileCacheManager, _fileDialogManager, _configuration, _dalamudUtil, PluginInterface);
_settingsUi = new SettingsUi(_windowSystem, _uiSharedComponent, _configuration, _apiController);
_compactUi = new CompactUi(_windowSystem, _uiSharedComponent, _configuration, _apiController);
_introUi = new IntroUi(_windowSystem, uiSharedComponent, _configuration, _fileCacheManager);
_mainUi.SwitchFromMainUiToIntro += () =>
_introUi = new IntroUi(_windowSystem, _uiSharedComponent, _configuration, _fileCacheManager);
_settingsUi.SwitchToIntroUi += () =>
{
_introUi.IsOpen = true;
_mainUi.IsOpen = false;
_settingsUi.IsOpen = false;
_compactUi.IsOpen = false;
};
_introUi.SwitchFromIntroToMainUi += () =>
_introUi.SwitchToMainUi += () =>
{
_introUi.IsOpen = false;
_mainUi.IsOpen = true;
_compactUi.IsOpen = true;
_fileCacheManager.StartWatchers();
ReLaunchCharacterManager();
};
_downloadUi = new DownloadUi(_windowSystem, _configuration, _apiController, uiSharedComponent);
_compactUi.OpenSettingsUi += () =>
{
_settingsUi.Toggle();
};
_downloadUi = new DownloadUi(_windowSystem, _configuration, _apiController, _uiSharedComponent);
_dalamudUtil.LogIn += DalamudUtilOnLogIn;
@@ -92,8 +101,8 @@ namespace MareSynchronos
private void ApiControllerOnRegisterFinalized()
{
_mainUi.IsOpen = false;
_introUi.IsOpen = true;
_introUi.IsOpen = false;
_compactUi.IsOpen = true;
}
public string Name => "Mare Synchronos";
@@ -107,9 +116,11 @@ namespace MareSynchronos
_dalamudUtil.LogIn -= DalamudUtilOnLogIn;
_dalamudUtil.LogOut -= DalamudUtilOnLogOut;
_mainUi?.Dispose();
_uiSharedComponent.Dispose();
_settingsUi?.Dispose();
_introUi?.Dispose();
_downloadUi?.Dispose();
_compactUi?.Dispose();
_fileCacheManager?.Dispose();
_ipcManager?.Dispose();
@@ -124,7 +135,7 @@ namespace MareSynchronos
Logger.Debug("Client login");
PluginInterface.UiBuilder.Draw += Draw;
PluginInterface.UiBuilder.OpenConfigUi += OpenConfigUi;
PluginInterface.UiBuilder.OpenConfigUi += OpenUi;
_commandManager.AddHandler(CommandName, new CommandInfo(OnCommand)
{
HelpMessage = "Opens the Mare Synchronos UI"
@@ -147,7 +158,7 @@ namespace MareSynchronos
_characterCacheManager?.Dispose();
_playerManager?.Dispose();
PluginInterface.UiBuilder.Draw -= Draw;
PluginInterface.UiBuilder.OpenConfigUi -= OpenConfigUi;
PluginInterface.UiBuilder.OpenConfigUi -= OpenUi;
_commandManager.RemoveHandler(CommandName);
}
@@ -191,14 +202,14 @@ namespace MareSynchronos
{
if (string.IsNullOrEmpty(args))
{
_mainUi.Toggle();
OpenUi();
}
}
private void OpenConfigUi()
private void OpenUi()
{
if (_configuration.HasValidSetup())
_mainUi.Toggle();
_compactUi.Toggle();
else
_introUi.Toggle();
}

View File

@@ -0,0 +1,437 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Reflection;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Components;
using Dalamud.Interface.Windowing;
using Dalamud.Utility;
using ImGuiNET;
using MareSynchronos.API;
using MareSynchronos.Utils;
using MareSynchronos.WebAPI;
namespace MareSynchronos.UI
{
public class CompactUi : Window, IDisposable
{
private readonly ApiController _apiController;
private readonly Configuration _configuration;
private readonly UiShared _uiShared;
private readonly WindowSystem _windowSystem;
private string _characterOrCommentFilter = string.Empty;
private string _pairToAdd = string.Empty;
private float _transferPartHeight = 0;
private float _windowContentWidth = 0;
public CompactUi(WindowSystem windowSystem,
UiShared uiShared, Configuration configuration, ApiController apiController) : base("Mare Synchronos " + Assembly.GetExecutingAssembly().GetName().Version)
{
Logger.Verbose("Creating " + nameof(CompactUi));
_windowSystem = windowSystem;
_uiShared = uiShared;
_configuration = configuration;
_apiController = apiController;
SizeConstraints = new WindowSizeConstraints()
{
MinimumSize = new Vector2(300, 200),
MaximumSize = new Vector2(300, 2000),
};
windowSystem.AddWindow(this);
}
public event SwitchUi? OpenSettingsUi;
public void Dispose()
{
Logger.Verbose("Disposing " + nameof(CompactUi));
_windowSystem.RemoveWindow(this);
}
public override void Draw()
{
_windowContentWidth = ImGui.GetWindowContentRegionWidth();
DrawUIDHeader();
ImGui.Separator();
if (_apiController.ServerState is not ServerState.Offline)
{
DrawServerStatus();
}
if (_apiController.ServerState is ServerState.Connected)
{
ImGui.Separator();
DrawPairList();
ImGui.Separator();
DrawTransfers();
_transferPartHeight = ImGui.GetCursorPosY() - _transferPartHeight;
}
}
private void DrawAddPair()
{
ImGui.PushID("pairs");
var buttonSize = GetIconButtonSize(FontAwesomeIcon.Plus);
ImGui.SetNextItemWidth(ImGui.GetWindowContentRegionWidth() - ImGui.GetWindowContentRegionMin().X - buttonSize.X);
ImGui.InputTextWithHint("##otheruid", "Other players UID", ref _pairToAdd, 10);
ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + ImGui.GetWindowContentRegionWidth() - buttonSize.X);
if (ImGuiComponents.IconButton(FontAwesomeIcon.Plus))
{
if (_apiController.PairedClients.All(w => w.OtherUID != _pairToAdd))
{
_ = _apiController.SendPairedClientAddition(_pairToAdd);
_pairToAdd = string.Empty;
}
}
AttachToolTip("Pair with " + (_pairToAdd.IsNullOrEmpty() ? "other user" : _pairToAdd));
ImGuiHelpers.ScaledDummy(2);
ImGui.PopID();
}
private void DrawFilter()
{
ImGui.PushID("filter");
ImGui.SetNextItemWidth(_windowContentWidth);
ImGui.InputTextWithHint("##filter", "Filter for UID/notes", ref _characterOrCommentFilter, 255);
ImGui.PopID();
}
private void DrawPairedClient(ClientPairDto entry)
{
ImGui.PushID(entry.OtherUID);
var pauseIcon = entry.IsPaused ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause;
var buttonSize = GetIconButtonSize(pauseIcon);
var textSize = ImGui.CalcTextSize(_apiController.SystemInfoDto.CpuUsage.ToString("0.00") + "%");
var originalY = ImGui.GetCursorPosY();
var textPos = originalY + buttonSize.Y / 2 - textSize.Y / 2;
ImGui.SetCursorPosY(textPos);
if (!entry.IsSynced)
{
ImGui.PushFont(UiBuilder.IconFont);
UiShared.ColorText(FontAwesomeIcon.ArrowUp.ToIconString(), ImGuiColors.DalamudRed);
ImGui.PopFont();
AttachToolTip(entry.OtherUID + " has not added you back");
}
else if (entry.IsPaused || entry.IsPausedFromOthers)
{
ImGui.PushFont(UiBuilder.IconFont);
UiShared.ColorText(FontAwesomeIcon.PauseCircle.ToIconString(), ImGuiColors.DalamudYellow);
ImGui.PopFont();
AttachToolTip("Pairing status with " + entry.OtherUID + " is paused");
}
else
{
ImGui.PushFont(UiBuilder.IconFont);
UiShared.ColorText(FontAwesomeIcon.Check.ToIconString(), ImGuiColors.ParsedGreen);
ImGui.PopFont();
AttachToolTip("You are paired with " + entry.OtherUID);
}
ImGui.SameLine();
ImGui.SetCursorPosY(textPos);
ImGui.Text(entry.OtherUID);
ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + ImGui.GetWindowContentRegionWidth() - buttonSize.X);
ImGui.SetCursorPosY(originalY);
if (ImGuiComponents.IconButton(pauseIcon))
{
_ = _apiController.SendPairedClientPauseChange(entry.OtherUID, !entry.IsPaused);
}
AttachToolTip(entry.IsSynced
? "Pause pairing with " + entry.OtherUID
: "Resume pairing with " + entry.OtherUID);
string charComment = _configuration.GetCurrentServerUidComments().ContainsKey(entry.OtherUID) ? _configuration.GetCurrentServerUidComments()[entry.OtherUID] : string.Empty;
buttonSize = GetIconButtonSize(FontAwesomeIcon.Trash);
ImGui.SetNextItemWidth(ImGui.GetWindowContentRegionMin().X + ImGui.GetWindowContentRegionWidth() - buttonSize.X - ImGui.GetStyle().ItemSpacing.X);
if (ImGui.InputTextWithHint("##comment", "Nick/Notes", ref charComment, 255))
{
if (_configuration.GetCurrentServerUidComments().Count == 0)
{
_configuration.UidServerComments[_configuration.ApiUri] =
new Dictionary<string, string>();
}
_configuration.SetCurrentServerUidComment(entry.OtherUID, charComment);
_configuration.Save();
}
ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + ImGui.GetWindowContentRegionWidth() - buttonSize.X);
if (ImGuiComponents.IconButton(FontAwesomeIcon.Trash))
{
if (ImGui.GetIO().KeyCtrl)
{
_ = _apiController.SendPairedClientRemoval(entry.OtherUID);
_apiController.PairedClients.Remove(entry);
}
}
AttachToolTip("Hold CTRL to unpair permanently from " + entry.OtherUID);
ImGuiHelpers.ScaledDummy(5);
ImGui.PopID();
}
private void AttachToolTip(string text)
{
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip(text);
}
}
private void DrawPairList()
{
ImGui.PushID("pairlist");
DrawAddPair();
DrawPairs();
_transferPartHeight = ImGui.GetCursorPosY();
DrawFilter();
ImGui.PopID();
}
private void DrawPairs()
{
ImGui.PushID("pairs");
var ySize = _transferPartHeight == 0
? 1
: (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - _transferPartHeight - ImGui.GetCursorPosY();
ImGui.BeginChild("list", new Vector2(_windowContentWidth, ySize), false);
foreach (var entry in _apiController.PairedClients.Where(p =>
{
if (_characterOrCommentFilter.IsNullOrEmpty()) return true;
_configuration.GetCurrentServerUidComments().TryGetValue(p.OtherUID, out string? comment);
return p.OtherUID.ToLower().Contains(_characterOrCommentFilter.ToLower()) || (comment?.ToLower().Contains(_characterOrCommentFilter.ToLower()) ?? false);
}).ToList())
{
DrawPairedClient(entry);
}
ImGui.EndChild();
ImGui.PopID();
}
private void DrawServerStatus()
{
ImGui.PushID("serverstate");
if (_apiController.ServerAlive)
{
var buttonSize = GetIconButtonSize(FontAwesomeIcon.Link);
var textSize = ImGui.CalcTextSize(_apiController.SystemInfoDto.CpuUsage.ToString("0.00") + "%");
var originalY = ImGui.GetCursorPosY();
var textPos = originalY + buttonSize.Y / 2 - textSize.Y / 2;
ImGui.SetCursorPosY(textPos);
ImGui.TextColored(ImGuiColors.ParsedGreen, _apiController.OnlineUsers.ToString());
ImGui.SameLine();
ImGui.SetCursorPosY(textPos);
ImGui.Text("Users Online");
ImGui.SameLine();
ImGui.SetCursorPosY(textPos);
UiShared.ColorText(_apiController.SystemInfoDto.CpuUsage.ToString("0.00") + "%", UiShared.GetCpuLoadColor(_apiController.SystemInfoDto.CpuUsage));
ImGui.SameLine();
ImGui.SetCursorPosY(textPos);
ImGui.Text("Load");
AttachToolTip("This is the current servers' CPU load");
ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + ImGui.GetWindowContentRegionWidth() - buttonSize.X);
ImGui.SetCursorPosY(originalY);
var serverIsConnected = _apiController.ServerState is ServerState.Connected;
var color = UiShared.GetBoolColor(serverIsConnected);
FontAwesomeIcon connectedIcon = serverIsConnected ? FontAwesomeIcon.Link : FontAwesomeIcon.Unlink;
ImGui.PushStyleColor(ImGuiCol.Text, color);
if (ImGuiComponents.IconButton(connectedIcon))
{
if (_apiController.ServerState == ServerState.Connected)
{
_configuration.FullPause = true;
_configuration.Save();
}
else
{
_configuration.FullPause = false;
_configuration.Save();
}
_ = _apiController.CreateConnections();
}
ImGui.PopStyleColor();
AttachToolTip(_apiController.IsConnected ? "Disconnect from " + _apiController.ServerDictionary[_configuration.ApiUri] : "Connect to " + _apiController.ServerDictionary[_configuration.ApiUri]);
}
else
{
UiShared.ColorTextWrapped("Server is offline", ImGuiColors.DalamudRed);
}
ImGui.PopID();
}
private void DrawTransfers()
{
ImGui.PushID("transfers");
var currentUploads = _apiController.CurrentUploads.ToList();
ImGui.PushFont(UiBuilder.IconFont);
ImGui.Text(FontAwesomeIcon.Upload.ToIconString());
ImGui.PopFont();
ImGui.SameLine(35);
if (currentUploads.Any())
{
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);
ImGui.Text($"{doneUploads}/{totalUploads}");
var uploadText = $"({UiShared.ByteToString(totalUploaded)}/{UiShared.ByteToString(totalToUpload)})";
var textSize = ImGui.CalcTextSize(uploadText);
ImGui.SameLine(_windowContentWidth - textSize.X);
ImGui.Text(uploadText);
}
else
{
ImGui.Text("No uploads in progress");
}
var currentDownloads = _apiController.CurrentDownloads.ToList();
ImGui.PushFont(UiBuilder.IconFont);
ImGui.Text(FontAwesomeIcon.Download.ToIconString());
ImGui.PopFont();
ImGui.SameLine(35);
if (currentDownloads.Any())
{
var totalDownloads = currentDownloads.Count;
var doneDownloads = currentDownloads.Count(c => c.IsTransferred);
var totalDownloaded = currentDownloads.Sum(c => c.Transferred);
var totalToDownload = currentDownloads.Sum(c => c.Total);
ImGui.Text($"{doneDownloads}/{totalDownloads}");
var downloadText =
$"({UiShared.ByteToString(totalDownloaded)}/{UiShared.ByteToString(totalToDownload)})";
var textSize = ImGui.CalcTextSize(downloadText);
ImGui.SameLine(_windowContentWidth - textSize.X);
ImGui.Text(downloadText);
}
else
{
ImGui.Text("No downloads in progress");
}
ImGui.SameLine();
ImGui.PopID();
}
private void DrawUIDHeader()
{
ImGui.PushID("header");
var uidText = GetUidText();
if (_uiShared.UidFontBuilt) ImGui.PushFont(_uiShared.UidFont);
var uidTextSize = ImGui.CalcTextSize(uidText);
if (_uiShared.UidFontBuilt) ImGui.PopFont();
var originalPos = ImGui.GetCursorPosY();
ImGui.SetWindowFontScale(1.5f);
var buttonSize = GetIconButtonSize(FontAwesomeIcon.Cog);
if (_apiController.ServerState is ServerState.Connected)
{
ImGui.SetCursorPosY(originalPos + uidTextSize.Y / 2 - buttonSize.Y / 2);
if (ImGuiComponents.IconButton(FontAwesomeIcon.Copy))
{
ImGui.SetClipboardText(_apiController.UID);
}
AttachToolTip("Copy your UID to clipboard");
ImGui.SameLine();
}
ImGui.SetWindowFontScale(1f);
ImGui.SetCursorPosY(originalPos - uidTextSize.Y / 8);
if (_uiShared.UidFontBuilt) ImGui.PushFont(_uiShared.UidFont);
ImGui.TextColored(GetUidColor(), uidText);
if (_uiShared.UidFontBuilt) ImGui.PopFont();
ImGui.SetWindowFontScale(1.5f);
ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + ImGui.GetWindowContentRegionWidth() - buttonSize.X);
ImGui.SetCursorPosY(originalPos + uidTextSize.Y / 2 - buttonSize.Y / 2);
if (ImGuiComponents.IconButton(FontAwesomeIcon.Cog))
{
OpenSettingsUi?.Invoke();
}
AttachToolTip("Open the Mare Synchronos Settings");
ImGui.SetWindowFontScale(1f);
if (_apiController.ServerState is not ServerState.Connected)
{
UiShared.ColorTextWrapped(GetServerError(), GetUidColor());
}
ImGui.PopID();
}
private Vector2 GetIconButtonSize(FontAwesomeIcon icon)
{
ImGui.PushFont(UiBuilder.IconFont);
var buttonSize = ImGuiHelpers.GetButtonSize(icon.ToIconString());
ImGui.PopFont();
return buttonSize;
}
private string GetServerError()
{
return _apiController.ServerState switch
{
ServerState.Disconnected => "You are currently disconnected from the Mare Synchronos server.",
ServerState.Unauthorized => "Your account is not present on the server anymore or you are banned.",
ServerState.Offline => "Your selected Mare Synchronos server is currently offline.",
ServerState.VersionMisMatch =>
"The plugin or server you are connecting to is outdated. Please update your plugin now. If you already did so, contact the server provider to update their server to the latest version.",
ServerState.NoAccount => "Idk how you got here but you have no account. What are you doing?",
ServerState.Connected => string.Empty,
_ => string.Empty
};
}
private Vector4 GetUidColor()
{
return _apiController.ServerState switch
{
ServerState.Connected => ImGuiColors.ParsedGreen,
ServerState.Disconnected => ImGuiColors.DalamudYellow,
ServerState.Unauthorized => ImGuiColors.DalamudRed,
ServerState.VersionMisMatch => ImGuiColors.DalamudRed,
ServerState.Offline => ImGuiColors.DalamudRed,
ServerState.NoAccount => ImGuiColors.DalamudRed,
_ => ImGuiColors.DalamudRed
};
}
private string GetUidText()
{
return _apiController.ServerState switch
{
ServerState.Disconnected => "Disconnected",
ServerState.Unauthorized => "Unauthorized",
ServerState.VersionMisMatch => "Version mismatch",
ServerState.Offline => "Unavailable",
ServerState.NoAccount => "No account",
ServerState.Connected => _apiController.UID,
_ => string.Empty
};
}
}
}

View File

@@ -14,9 +14,9 @@ namespace MareSynchronos.UI
private readonly Configuration _pluginConfiguration;
private readonly FileCacheManager _fileCacheManager;
private readonly WindowSystem _windowSystem;
private bool _readFirstPage = false;
private bool _readFirstPage;
public event SwitchUi? SwitchFromIntroToMainUi;
public event SwitchUi? SwitchToMainUi;
public void Dispose()
{
@@ -46,11 +46,6 @@ namespace MareSynchronos.UI
public override void Draw()
{
if (!IsOpen)
{
return;
}
if (!_pluginConfiguration.AcceptedAgreement && !_readFirstPage)
{
ImGui.SetWindowFontScale(1.3f);
@@ -152,6 +147,9 @@ namespace MareSynchronos.UI
ImGui.Separator();
if (_pluginConfiguration.ClientSecret.ContainsKey(_pluginConfiguration.ApiUri) && _uiShared.ShowClientSecret)
{
ImGui.SetWindowFontScale(2f);
UiShared.ColorTextWrapped("DO NOT GIVE THIS KEY TO OTHER PEOPLE.", ImGuiColors.DalamudRed);
ImGui.SetWindowFontScale(1f);
ImGui.Separator();
UiShared.TextWrapped(_pluginConfiguration.ClientSecret[_pluginConfiguration.ApiUri]);
ImGui.Separator();
@@ -169,7 +167,7 @@ namespace MareSynchronos.UI
ImGui.Separator();
if (ImGui.Button("Finish##finishIntro"))
{
SwitchFromIntroToMainUi?.Invoke();
SwitchToMainUi?.Invoke();
IsOpen = false;
}
}
@@ -183,7 +181,7 @@ namespace MareSynchronos.UI
"to verify who you are. It is directly tied to the UID you will be receiving. In case of loss, you will have to re-register an account.");
UiShared.TextWrapped("Do not ever, under any circumstances, share your secret key to anyone! Likewise do not share your Mare Synchronos plugin configuration to anyone!");
ImGui.PopStyleColor();
_uiShared.DrawServiceSelection(() => SwitchFromIntroToMainUi?.Invoke(), true);
_uiShared.DrawServiceSelection(() => SwitchToMainUi?.Invoke(), true);
}
}
}

View File

@@ -1,752 +0,0 @@
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Windowing;
using ImGuiNET;
using MareSynchronos.WebAPI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using MareSynchronos.API;
using MareSynchronos.Utils;
using MareSynchronos.WebAPI.Utils;
namespace MareSynchronos.UI
{
public delegate void SwitchUi();
public class MainUi : Window, IDisposable
{
private readonly Configuration _configuration;
private readonly WindowSystem _windowSystem;
private readonly ApiController _apiController;
private readonly UiShared _uiShared;
public event SwitchUi? SwitchFromMainUiToIntro;
public MainUi(WindowSystem windowSystem,
UiShared uiShared, Configuration configuration, ApiController apiController) : base("Mare Synchronos Settings", ImGuiWindowFlags.None)
{
Logger.Verbose("Creating " + nameof(MainUi));
SizeConstraints = new WindowSizeConstraints()
{
MinimumSize = new Vector2(800, 400),
MaximumSize = new Vector2(800, 2000),
};
_configuration = configuration;
_windowSystem = windowSystem;
_apiController = apiController;
_uiShared = uiShared;
windowSystem.AddWindow(this);
}
public void Dispose()
{
Logger.Verbose("Disposing " + nameof(MainUi));
_windowSystem.RemoveWindow(this);
}
public override void Draw()
{
if (!IsOpen)
{
return;
}
var pluginState = _uiShared.DrawOtherPluginState();
if (pluginState)
DrawSettingsContent();
}
private void DrawSettingsContent()
{
_uiShared.PrintServerState();
ImGui.Separator();
if (_apiController.ServerState is ServerState.Connected)
{
ImGui.SetWindowFontScale(1.2f);
ImGui.Text("Your UID");
ImGui.SameLine();
ImGui.TextColored(ImGuiColors.ParsedGreen, _apiController.UID);
ImGui.SameLine();
ImGui.SetWindowFontScale(1.0f);
if (ImGui.Button("Copy UID"))
{
ImGui.SetClipboardText(_apiController.UID);
}
ImGui.Text("Share this UID to other Mare users so they pair their client with yours.");
}
else
{
string errorMsg = _apiController.ServerState switch
{
ServerState.Disconnected => "Disconnected",
ServerState.Unauthorized => "Unauthorized",
ServerState.VersionMisMatch => "Service version mismatch",
ServerState.Offline => "Service unavailable",
ServerState.NoAccount => "No account",
};
ImGui.SetWindowFontScale(1.2f);
ImGui.TextColored(ImGuiColors.DalamudRed, $"No UID ({errorMsg})");
ImGui.SetWindowFontScale(1.0f);
switch (_apiController.ServerState)
{
case ServerState.Disconnected:
UiShared.ColorTextWrapped("You are currently disconnected from the Mare Synchronos service.", ImGuiColors.DalamudRed);
break;
case ServerState.Unauthorized:
UiShared.ColorTextWrapped("Your account is not present on the service anymore or you are banned.", ImGuiColors.DalamudRed);
UiShared.ColorTextWrapped("If you think your secret key is just invalid, use the following button to reset " +
"the local secret key to be able to re-register. If you continue to see this message after " +
"registering, tough luck, asshole.", ImGuiColors.DalamudYellow);
if (ImGui.Button("Reset Secret Key"))
{
_configuration.ClientSecret.Remove(_configuration.ApiUri);
_configuration.Save();
SwitchFromMainUiToIntro?.Invoke();
}
break;
case ServerState.Offline:
UiShared.ColorTextWrapped("Your selected Mare Synchronos server is currently offline.", ImGuiColors.DalamudRed);
break;
case ServerState.VersionMisMatch:
UiShared.ColorTextWrapped("The server or your client is outdated. If the client has recently been updated for breaking " +
"service changes, the service must follow suit.", ImGuiColors.DalamudRed);
break;
case ServerState.Connected:
default:
break;
}
}
ImGui.Separator();
if (_apiController.IsConnected)
DrawPairedClientsContent();
DrawFileCacheSettings();
if (_apiController.IsConnected)
DrawCurrentTransfers();
DrawBlockedTransfers();
DrawUserAdministration(_apiController.IsConnected);
if (_apiController.IsConnected && _apiController.IsModerator)
DrawAdministration();
}
private string _forbiddenFileHashEntry = string.Empty;
private string _forbiddenFileHashForbiddenBy = string.Empty;
private string _bannedUserHashEntry = string.Empty;
private string _bannedUserReasonEntry = string.Empty;
private void DrawAdministration()
{
if (ImGui.TreeNode("Administrative Actions"))
{
if (ImGui.TreeNode("Forbidden Files Changes"))
{
if (ImGui.BeginTable("ForbiddenFilesTable", 3, ImGuiTableFlags.RowBg))
{
ImGui.TableSetupColumn("File Hash", ImGuiTableColumnFlags.None, 290);
ImGui.TableSetupColumn("Forbidden By", ImGuiTableColumnFlags.None, 290);
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 70);
ImGui.TableHeadersRow();
foreach (var forbiddenFile in _apiController.AdminForbiddenFiles)
{
ImGui.TableNextColumn();
ImGui.Text(forbiddenFile.Hash);
ImGui.TableNextColumn();
string by = forbiddenFile.ForbiddenBy;
if (ImGui.InputText("##forbiddenBy" + forbiddenFile.Hash, ref by, 255))
{
forbiddenFile.ForbiddenBy = by;
}
ImGui.TableNextColumn();
if (_apiController.IsAdmin)
{
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(
FontAwesomeIcon.Upload.ToIconString() + "##updateFile" + forbiddenFile.Hash))
{
_ = _apiController.AddOrUpdateForbiddenFileEntry(forbiddenFile);
}
ImGui.SameLine();
if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString() + "##deleteFile" +
forbiddenFile.Hash))
{
_ = _apiController.DeleteForbiddenFileEntry(forbiddenFile);
}
ImGui.PopFont();
}
}
if (_apiController.IsAdmin)
{
ImGui.TableNextColumn();
ImGui.InputText("##addFileHash", ref _forbiddenFileHashEntry, 255);
ImGui.TableNextColumn();
ImGui.InputText("##addForbiddenBy", ref _forbiddenFileHashForbiddenBy, 255);
ImGui.TableNextColumn();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.Plus.ToIconString() + "##addForbiddenFile"))
{
_ = _apiController.AddOrUpdateForbiddenFileEntry(new ForbiddenFileDto()
{
ForbiddenBy = _forbiddenFileHashForbiddenBy,
Hash = _forbiddenFileHashEntry
});
}
ImGui.PopFont();
ImGui.NextColumn();
}
ImGui.EndTable();
}
ImGui.TreePop();
}
if (ImGui.TreeNode("Banned Users"))
{
if (ImGui.BeginTable("BannedUsersTable", 3, ImGuiTableFlags.RowBg))
{
ImGui.TableSetupColumn("Character Hash", ImGuiTableColumnFlags.None, 290);
ImGui.TableSetupColumn("Reason", ImGuiTableColumnFlags.None, 290);
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 70);
ImGui.TableHeadersRow();
foreach (var bannedUser in _apiController.AdminBannedUsers)
{
ImGui.TableNextColumn();
ImGui.Text(bannedUser.CharacterHash);
ImGui.TableNextColumn();
string reason = bannedUser.Reason;
ImGuiInputTextFlags moderatorFlags = _apiController.IsModerator
? ImGuiInputTextFlags.ReadOnly
: ImGuiInputTextFlags.None;
if (ImGui.InputText("##bannedReason" + bannedUser.CharacterHash, ref reason, 255,
moderatorFlags))
{
bannedUser.Reason = reason;
}
ImGui.TableNextColumn();
ImGui.PushFont(UiBuilder.IconFont);
if (_apiController.IsAdmin)
{
if (ImGui.Button(FontAwesomeIcon.Upload.ToIconString() + "##updateUser" +
bannedUser.CharacterHash))
{
_ = _apiController.AddOrUpdateBannedUserEntry(bannedUser);
}
ImGui.SameLine();
}
if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString() + "##deleteUser" +
bannedUser.CharacterHash))
{
_ = _apiController.DeleteBannedUserEntry(bannedUser);
}
ImGui.PopFont();
}
ImGui.TableNextColumn();
ImGui.InputText("##addUserHash", ref _bannedUserHashEntry, 255);
ImGui.TableNextColumn();
if (_apiController.IsAdmin)
{
ImGui.InputText("##addUserReason", ref _bannedUserReasonEntry, 255);
}
else
{
_bannedUserReasonEntry = "Banned by " + _uiShared.PlayerName;
ImGui.InputText("##addUserReason", ref _bannedUserReasonEntry, 255,
ImGuiInputTextFlags.ReadOnly);
}
ImGui.TableNextColumn();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.Plus.ToIconString() + "##addForbiddenFile"))
{
_ = _apiController.AddOrUpdateBannedUserEntry(new BannedUserDto()
{
CharacterHash = _forbiddenFileHashForbiddenBy,
Reason = _forbiddenFileHashEntry
});
}
ImGui.PopFont();
ImGui.EndTable();
}
ImGui.TreePop();
}
if (ImGui.TreeNode("Online Users"))
{
if (ImGui.Button("Refresh Online Users"))
{
_ = _apiController.RefreshOnlineUsers();
}
if (ImGui.BeginTable("OnlineUsersTable", 3, ImGuiTableFlags.RowBg))
{
ImGui.TableSetupColumn("UID", ImGuiTableColumnFlags.None, 100);
ImGui.TableSetupColumn("Character Hash", ImGuiTableColumnFlags.None, 300);
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 70);
ImGui.TableHeadersRow();
foreach (var onlineUser in _apiController.AdminOnlineUsers)
{
ImGui.TableNextColumn();
ImGui.PushFont(UiBuilder.IconFont);
string icon = onlineUser.IsModerator
? FontAwesomeIcon.ChessKing.ToIconString()
: onlineUser.IsAdmin
? FontAwesomeIcon.Crown.ToIconString()
: FontAwesomeIcon.User.ToIconString();
ImGui.Text(icon);
ImGui.PopFont();
ImGui.SameLine();
ImGui.Text(onlineUser.UID);
ImGui.SameLine();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.Copy.ToIconString() + "##onlineUserCopyUID" +
onlineUser.CharacterNameHash))
{
ImGui.SetClipboardText(onlineUser.UID);
}
ImGui.PopFont();
ImGui.TableNextColumn();
string charNameHash = onlineUser.CharacterNameHash;
ImGui.InputText("##onlineUserHash" + onlineUser.CharacterNameHash, ref charNameHash, 255,
ImGuiInputTextFlags.ReadOnly);
ImGui.SameLine();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.Copy.ToIconString() + "##onlineUserCopyHash" +
onlineUser.CharacterNameHash))
{
ImGui.SetClipboardText(onlineUser.UID);
}
ImGui.PopFont();
ImGui.TableNextColumn();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.SkullCrossbones.ToIconString() + "##onlineUserBan" +
onlineUser.CharacterNameHash))
{
_ = _apiController.AddOrUpdateBannedUserEntry(new BannedUserDto
{
CharacterHash = onlineUser.CharacterNameHash,
Reason = "Banned by " + _uiShared.PlayerName
});
}
ImGui.SameLine();
if (onlineUser.UID != _apiController.UID && _apiController.IsAdmin)
{
if (!onlineUser.IsModerator)
{
if (ImGui.Button(FontAwesomeIcon.ChessKing.ToIconString() +
"##onlineUserModerator" +
onlineUser.CharacterNameHash))
{
_apiController.PromoteToModerator(onlineUser.UID);
}
}
else
{
if (ImGui.Button(FontAwesomeIcon.User.ToIconString() +
"##onlineUserNonModerator" +
onlineUser.CharacterNameHash))
{
_apiController.DemoteFromModerator(onlineUser.UID);
}
}
}
ImGui.PopFont();
}
ImGui.EndTable();
}
ImGui.TreePop();
}
ImGui.TreePop();
}
}
private bool _deleteFilesPopupModalShown = false;
private bool _deleteAccountPopupModalShown = false;
private void DrawUserAdministration(bool serverAlive)
{
if (ImGui.TreeNode(
$"User Administration"))
{
if (serverAlive)
{
if (ImGui.Button("Delete all my files"))
{
_deleteFilesPopupModalShown = true;
ImGui.OpenPopup("Delete all your files?");
}
UiShared.DrawHelpText("Completely deletes all your uploaded files on the service.");
if (ImGui.BeginPopupModal("Delete all your files?", ref _deleteFilesPopupModalShown,
ImGuiWindowFlags.AlwaysAutoResize))
{
UiShared.TextWrapped(
"All your own uploaded files on the service will be deleted.\nThis operation cannot be undone.");
ImGui.Text("Are you sure you want to continue?");
ImGui.Separator();
if (ImGui.Button("Delete everything", new Vector2(150, 0)))
{
Task.Run(() => _apiController.DeleteAllMyFiles());
ImGui.CloseCurrentPopup();
_deleteFilesPopupModalShown = false;
}
ImGui.SameLine();
if (ImGui.Button("Cancel##cancelDelete", new Vector2(150, 0)))
{
ImGui.CloseCurrentPopup();
_deleteFilesPopupModalShown = false;
}
ImGui.EndPopup();
}
if (ImGui.Button("Delete account"))
{
_deleteAccountPopupModalShown = true;
ImGui.OpenPopup("Delete your account?");
}
UiShared.DrawHelpText("Completely deletes your account and all uploaded files to the service.");
if (ImGui.BeginPopupModal("Delete your account?", ref _deleteAccountPopupModalShown,
ImGuiWindowFlags.AlwaysAutoResize))
{
UiShared.TextWrapped(
"Your account and all associated files and data on the service will be deleted.");
UiShared.TextWrapped("Your UID will be removed from all pairing lists.");
ImGui.Text("Are you sure you want to continue?");
ImGui.Separator();
if (ImGui.Button("Delete account", new Vector2(150, 0)))
{
Task.Run(() => _apiController.DeleteAccount());
ImGui.CloseCurrentPopup();
_deleteAccountPopupModalShown = false;
SwitchFromMainUiToIntro?.Invoke();
}
ImGui.SameLine();
if (ImGui.Button("Cancel##cancelDelete", new Vector2(150, 0)))
{
ImGui.CloseCurrentPopup();
_deleteAccountPopupModalShown = false;
}
ImGui.EndPopup();
}
}
if (!_configuration.FullPause)
{
UiShared.ColorTextWrapped("Note: to change servers you need to disconnect from your current Mare Synchronos server.", ImGuiColors.DalamudYellow);
}
var marePaused = _configuration.FullPause;
if (_configuration.HasValidSetup())
{
if (ImGui.Checkbox("Disconnect Mare Synchronos", ref marePaused))
{
_configuration.FullPause = marePaused;
_configuration.Save();
Task.Run(_apiController.CreateConnections);
}
UiShared.DrawHelpText("Completely pauses the sync and clears your current data (not uploaded files) on the service.");
}
else
{
UiShared.ColorText("You cannot reconnect without a valid account on the service.", ImGuiColors.DalamudYellow);
}
if (marePaused)
{
_uiShared.DrawServiceSelection(() => SwitchFromMainUiToIntro?.Invoke());
}
ImGui.TreePop();
}
}
private void DrawBlockedTransfers()
{
if (ImGui.TreeNode(
$"Forbidden Transfers"))
{
UiShared.ColorTextWrapped("Files that you attempted to upload or download that were forbidden to be transferred by their creators will appear here. " +
"If you see file paths from your drive here, then those files were not allowed to be uploaded. If you see hashes, those files were not allowed to be downloaded. " +
"Ask your paired friend to send you the mod in question through other means, acquire the mod yourself or pester the mod creator to allow it to be sent over Mare.",
ImGuiColors.DalamudGrey);
if (ImGui.BeginTable("TransfersTable", 2, ImGuiTableFlags.SizingStretchProp))
{
ImGui.TableSetupColumn(
$"Hash/Filename");
ImGui.TableSetupColumn($"Forbidden by");
ImGui.TableHeadersRow();
foreach (var item in _apiController.ForbiddenTransfers)
{
ImGui.TableNextColumn();
if (item is UploadFileTransfer transfer)
{
ImGui.Text(transfer.LocalFile);
}
else
{
ImGui.Text(item.Hash);
}
ImGui.TableNextColumn();
ImGui.Text(item.ForbiddenBy);
}
ImGui.EndTable();
}
ImGui.TreePop();
}
}
private void DrawCurrentTransfers()
{
if (ImGui.TreeNode(
$"Current Transfers"))
{
bool showTransferWindow = _configuration.ShowTransferWindow;
if (ImGui.Checkbox("Show separate Transfer window while transfers are active", ref showTransferWindow))
{
_configuration.ShowTransferWindow = showTransferWindow;
_configuration.Save();
}
if (_configuration.ShowTransferWindow)
{
ImGui.Indent();
bool editTransferWindowPosition = _uiShared.EditTrackerPosition;
if (ImGui.Checkbox("Edit Transfer Window position", ref editTransferWindowPosition))
{
_uiShared.EditTrackerPosition = editTransferWindowPosition;
}
ImGui.Unindent();
}
if (ImGui.BeginTable("TransfersTable", 2))
{
ImGui.TableSetupColumn(
$"Uploads ({UiShared.ByteToString(_apiController.CurrentUploads.Sum(a => a.Transferred))} / {UiShared.ByteToString(_apiController.CurrentUploads.Sum(a => a.Total))})");
ImGui.TableSetupColumn($"Downloads ({UiShared.ByteToString(_apiController.CurrentDownloads.Sum(a => a.Transferred))} / {UiShared.ByteToString(_apiController.CurrentDownloads.Sum(a => a.Total))})");
ImGui.TableHeadersRow();
ImGui.TableNextColumn();
if (ImGui.BeginTable("UploadsTable", 3))
{
ImGui.TableSetupColumn("File");
ImGui.TableSetupColumn("Uploaded");
ImGui.TableSetupColumn("Size");
ImGui.TableHeadersRow();
foreach (var transfer in _apiController.CurrentUploads.ToArray())
{
var color = UiShared.UploadColor((transfer.Transferred, transfer.Total));
ImGui.PushStyleColor(ImGuiCol.Text, color);
ImGui.TableNextColumn();
ImGui.Text(transfer.Hash);
ImGui.TableNextColumn();
ImGui.Text(UiShared.ByteToString(transfer.Transferred));
ImGui.TableNextColumn();
ImGui.Text(UiShared.ByteToString(transfer.Total));
ImGui.PopStyleColor();
ImGui.TableNextRow();
}
ImGui.EndTable();
}
ImGui.TableNextColumn();
if (ImGui.BeginTable("DownloadsTable", 3))
{
ImGui.TableSetupColumn("File");
ImGui.TableSetupColumn("Downloaded");
ImGui.TableSetupColumn("Size");
ImGui.TableHeadersRow();
foreach (var transfer in _apiController.CurrentDownloads.ToArray())
{
var color = UiShared.UploadColor((transfer.Transferred, transfer.Total));
ImGui.PushStyleColor(ImGuiCol.Text, color);
ImGui.TableNextColumn();
ImGui.Text(transfer.Hash);
ImGui.TableNextColumn();
ImGui.Text(UiShared.ByteToString(transfer.Transferred));
ImGui.TableNextColumn();
ImGui.Text(UiShared.ByteToString(transfer.Total));
ImGui.PopStyleColor();
ImGui.TableNextRow();
}
ImGui.EndTable();
}
ImGui.EndTable();
}
ImGui.TreePop();
}
}
private void DrawFileCacheSettings()
{
if (ImGui.TreeNode("File Cache Settings"))
{
_uiShared.DrawFileScanState();
_uiShared.DrawCacheDirectorySetting();
ImGui.Text($"Local cache size: {UiShared.ByteToString(_uiShared.FileCacheSize)}");
ImGui.SameLine();
if (ImGui.Button("Clear local cache"))
{
Task.Run(() =>
{
foreach (var file in Directory.GetFiles(_configuration.CacheFolder))
{
File.Delete(file);
}
});
}
ImGui.TreePop();
}
}
public override void OnClose()
{
_uiShared.EditTrackerPosition = false;
base.OnClose();
}
private void DrawPairedClientsContent()
{
if (!_apiController.ServerAlive) return;
if (ImGui.TreeNode("Pairing Configuration"))
{
if (ImGui.BeginTable("PairedClientsTable", 5))
{
ImGui.TableSetupColumn("Pause", ImGuiTableColumnFlags.WidthFixed, 50);
ImGui.TableSetupColumn("UID", ImGuiTableColumnFlags.WidthFixed, 110);
ImGui.TableSetupColumn("Status", ImGuiTableColumnFlags.WidthFixed, 140);
ImGui.TableSetupColumn("Comment", ImGuiTableColumnFlags.WidthFixed, 400);
ImGui.TableSetupColumn("", ImGuiTableColumnFlags.WidthFixed, 70);
ImGui.TableHeadersRow();
foreach (var item in _apiController.PairedClients.ToList())
{
ImGui.TableNextColumn();
ImGui.PushFont(UiBuilder.IconFont);
string pauseIcon = item.IsPaused ? FontAwesomeIcon.Play.ToIconString() : FontAwesomeIcon.Pause.ToIconString();
if (ImGui.Button(pauseIcon + "##paused" + item.OtherUID))
{
_ = _apiController.SendPairedClientPauseChange(item.OtherUID, !item.IsPaused);
}
ImGui.PopFont();
ImGui.TableNextColumn();
ImGui.TextColored(
UiShared.GetBoolColor(item.IsSynced && !item.IsPausedFromOthers && !item.IsPaused),
item.OtherUID);
ImGui.TableNextColumn();
string pairString = !item.IsSynced
? "Has not added you"
: ((item.IsPaused || item.IsPausedFromOthers) ? "Unpaired" : "Paired");
ImGui.TextColored(UiShared.GetBoolColor(item.IsSynced && !item.IsPaused && !item.IsPausedFromOthers), pairString);
ImGui.TableNextColumn();
string charComment = _configuration.GetCurrentServerUidComments().ContainsKey(item.OtherUID) ? _configuration.GetCurrentServerUidComments()[item.OtherUID] : string.Empty;
ImGui.SetNextItemWidth(400);
if (ImGui.InputTextWithHint("##comment" + item.OtherUID, "Add your comment here (comments will not be synced)", ref charComment, 255))
{
if (_configuration.GetCurrentServerUidComments().Count == 0)
{
_configuration.UidServerComments[_configuration.ApiUri] =
new Dictionary<string, string>();
}
_configuration.SetCurrentServerUidComment(item.OtherUID, charComment);
_configuration.Save();
}
ImGui.TableNextColumn();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString() + "##" + item.OtherUID))
{
_ = _apiController.SendPairedClientRemoval(item.OtherUID);
_apiController.PairedClients.Remove(item);
}
ImGui.PopFont();
ImGui.TableNextRow();
}
ImGui.EndTable();
}
var pairedClientEntry = _tempNameUID;
ImGui.SetNextItemWidth(200);
if (ImGui.InputText("UID", ref pairedClientEntry, 20))
{
_tempNameUID = pairedClientEntry;
}
ImGui.SameLine();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.Plus.ToIconString() + "##addToPairedClients"))
{
if (_apiController.PairedClients.All(w => w.OtherUID != _tempNameUID))
{
var nameToSend = _tempNameUID;
_tempNameUID = string.Empty;
_ = _apiController.SendPairedClientAddition(nameToSend);
}
}
ImGui.PopFont();
ImGui.TreePop();
}
}
private string _tempNameUID = string.Empty;
}
}

View File

@@ -0,0 +1,603 @@
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Windowing;
using ImGuiNET;
using MareSynchronos.WebAPI;
using System;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using MareSynchronos.API;
using MareSynchronos.Utils;
using MareSynchronos.WebAPI.Utils;
namespace MareSynchronos.UI
{
public delegate void SwitchUi();
public class SettingsUi : Window, IDisposable
{
private readonly Configuration _configuration;
private readonly WindowSystem _windowSystem;
private readonly ApiController _apiController;
private readonly UiShared _uiShared;
public event SwitchUi? SwitchToIntroUi;
public SettingsUi(WindowSystem windowSystem,
UiShared uiShared, Configuration configuration, ApiController apiController) : base("Mare Synchronos Settings")
{
Logger.Verbose("Creating " + nameof(SettingsUi));
SizeConstraints = new WindowSizeConstraints()
{
MinimumSize = new Vector2(800, 400),
MaximumSize = new Vector2(800, 2000),
};
_configuration = configuration;
_windowSystem = windowSystem;
_apiController = apiController;
_uiShared = uiShared;
windowSystem.AddWindow(this);
}
public void Dispose()
{
Logger.Verbose("Disposing " + nameof(SettingsUi));
_windowSystem.RemoveWindow(this);
}
public override void Draw()
{
var pluginState = _uiShared.DrawOtherPluginState();
DrawSettingsContent();
}
private void DrawSettingsContent()
{
_uiShared.PrintServerState();
ImGui.Separator();
if (ImGui.BeginTabBar("mainTabBar"))
{
if (ImGui.BeginTabItem("Cache Settings"))
{
DrawFileCacheSettings();
ImGui.EndTabItem();
}
if (_apiController.ServerState is ServerState.Connected)
{
if (ImGui.BeginTabItem("Transfers"))
{
DrawCurrentTransfers();
ImGui.EndTabItem();
}
}
if (ImGui.BeginTabItem("Blocked Transfers"))
{
DrawBlockedTransfers();
ImGui.EndTabItem();
}
if (ImGui.BeginTabItem("User Administration"))
{
DrawUserAdministration(_apiController.IsConnected);
ImGui.EndTabItem();
}
if (_apiController.IsConnected && _apiController.IsModerator)
{
if (ImGui.BeginTabItem("Administration"))
{
DrawAdministration();
ImGui.EndTabItem();
}
}
ImGui.EndTabBar();
}
}
private string _forbiddenFileHashEntry = string.Empty;
private string _forbiddenFileHashForbiddenBy = string.Empty;
private string _bannedUserHashEntry = string.Empty;
private string _bannedUserReasonEntry = string.Empty;
private void DrawAdministration()
{
if (ImGui.TreeNode("Forbidden Files Changes"))
{
if (ImGui.BeginTable("ForbiddenFilesTable", 3, ImGuiTableFlags.RowBg))
{
ImGui.TableSetupColumn("File Hash", ImGuiTableColumnFlags.None, 290);
ImGui.TableSetupColumn("Forbidden By", ImGuiTableColumnFlags.None, 290);
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 70);
ImGui.TableHeadersRow();
foreach (var forbiddenFile in _apiController.AdminForbiddenFiles)
{
ImGui.TableNextColumn();
ImGui.Text(forbiddenFile.Hash);
ImGui.TableNextColumn();
string by = forbiddenFile.ForbiddenBy;
if (ImGui.InputText("##forbiddenBy" + forbiddenFile.Hash, ref by, 255))
{
forbiddenFile.ForbiddenBy = by;
}
ImGui.TableNextColumn();
if (_apiController.IsAdmin)
{
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(
FontAwesomeIcon.Upload.ToIconString() + "##updateFile" + forbiddenFile.Hash))
{
_ = _apiController.AddOrUpdateForbiddenFileEntry(forbiddenFile);
}
ImGui.SameLine();
if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString() + "##deleteFile" +
forbiddenFile.Hash))
{
_ = _apiController.DeleteForbiddenFileEntry(forbiddenFile);
}
ImGui.PopFont();
}
}
if (_apiController.IsAdmin)
{
ImGui.TableNextColumn();
ImGui.InputText("##addFileHash", ref _forbiddenFileHashEntry, 255);
ImGui.TableNextColumn();
ImGui.InputText("##addForbiddenBy", ref _forbiddenFileHashForbiddenBy, 255);
ImGui.TableNextColumn();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.Plus.ToIconString() + "##addForbiddenFile"))
{
_ = _apiController.AddOrUpdateForbiddenFileEntry(new ForbiddenFileDto()
{
ForbiddenBy = _forbiddenFileHashForbiddenBy,
Hash = _forbiddenFileHashEntry
});
}
ImGui.PopFont();
ImGui.NextColumn();
}
ImGui.EndTable();
}
ImGui.TreePop();
}
if (ImGui.TreeNode("Banned Users"))
{
if (ImGui.BeginTable("BannedUsersTable", 3, ImGuiTableFlags.RowBg))
{
ImGui.TableSetupColumn("Character Hash", ImGuiTableColumnFlags.None, 290);
ImGui.TableSetupColumn("Reason", ImGuiTableColumnFlags.None, 290);
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 70);
ImGui.TableHeadersRow();
foreach (var bannedUser in _apiController.AdminBannedUsers)
{
ImGui.TableNextColumn();
ImGui.Text(bannedUser.CharacterHash);
ImGui.TableNextColumn();
string reason = bannedUser.Reason;
ImGuiInputTextFlags moderatorFlags = _apiController.IsModerator
? ImGuiInputTextFlags.ReadOnly
: ImGuiInputTextFlags.None;
if (ImGui.InputText("##bannedReason" + bannedUser.CharacterHash, ref reason, 255,
moderatorFlags))
{
bannedUser.Reason = reason;
}
ImGui.TableNextColumn();
ImGui.PushFont(UiBuilder.IconFont);
if (_apiController.IsAdmin)
{
if (ImGui.Button(FontAwesomeIcon.Upload.ToIconString() + "##updateUser" +
bannedUser.CharacterHash))
{
_ = _apiController.AddOrUpdateBannedUserEntry(bannedUser);
}
ImGui.SameLine();
}
if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString() + "##deleteUser" +
bannedUser.CharacterHash))
{
_ = _apiController.DeleteBannedUserEntry(bannedUser);
}
ImGui.PopFont();
}
ImGui.TableNextColumn();
ImGui.InputText("##addUserHash", ref _bannedUserHashEntry, 255);
ImGui.TableNextColumn();
if (_apiController.IsAdmin)
{
ImGui.InputText("##addUserReason", ref _bannedUserReasonEntry, 255);
}
else
{
_bannedUserReasonEntry = "Banned by " + _uiShared.PlayerName;
ImGui.InputText("##addUserReason", ref _bannedUserReasonEntry, 255,
ImGuiInputTextFlags.ReadOnly);
}
ImGui.TableNextColumn();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.Plus.ToIconString() + "##addForbiddenFile"))
{
_ = _apiController.AddOrUpdateBannedUserEntry(new BannedUserDto()
{
CharacterHash = _forbiddenFileHashForbiddenBy,
Reason = _forbiddenFileHashEntry
});
}
ImGui.PopFont();
ImGui.EndTable();
}
ImGui.TreePop();
}
if (ImGui.TreeNode("Online Users"))
{
if (ImGui.Button("Refresh Online Users"))
{
_ = _apiController.RefreshOnlineUsers();
}
if (ImGui.BeginTable("OnlineUsersTable", 3, ImGuiTableFlags.RowBg))
{
ImGui.TableSetupColumn("UID", ImGuiTableColumnFlags.None, 100);
ImGui.TableSetupColumn("Character Hash", ImGuiTableColumnFlags.None, 300);
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 70);
ImGui.TableHeadersRow();
foreach (var onlineUser in _apiController.AdminOnlineUsers)
{
ImGui.TableNextColumn();
ImGui.PushFont(UiBuilder.IconFont);
string icon = onlineUser.IsModerator
? FontAwesomeIcon.ChessKing.ToIconString()
: onlineUser.IsAdmin
? FontAwesomeIcon.Crown.ToIconString()
: FontAwesomeIcon.User.ToIconString();
ImGui.Text(icon);
ImGui.PopFont();
ImGui.SameLine();
ImGui.Text(onlineUser.UID);
ImGui.SameLine();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.Copy.ToIconString() + "##onlineUserCopyUID" +
onlineUser.CharacterNameHash))
{
ImGui.SetClipboardText(onlineUser.UID);
}
ImGui.PopFont();
ImGui.TableNextColumn();
string charNameHash = onlineUser.CharacterNameHash;
ImGui.InputText("##onlineUserHash" + onlineUser.CharacterNameHash, ref charNameHash, 255,
ImGuiInputTextFlags.ReadOnly);
ImGui.SameLine();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.Copy.ToIconString() + "##onlineUserCopyHash" +
onlineUser.CharacterNameHash))
{
ImGui.SetClipboardText(onlineUser.UID);
}
ImGui.PopFont();
ImGui.TableNextColumn();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.SkullCrossbones.ToIconString() + "##onlineUserBan" +
onlineUser.CharacterNameHash))
{
_ = _apiController.AddOrUpdateBannedUserEntry(new BannedUserDto
{
CharacterHash = onlineUser.CharacterNameHash,
Reason = "Banned by " + _uiShared.PlayerName
});
}
ImGui.SameLine();
if (onlineUser.UID != _apiController.UID && _apiController.IsAdmin)
{
if (!onlineUser.IsModerator)
{
if (ImGui.Button(FontAwesomeIcon.ChessKing.ToIconString() +
"##onlineUserModerator" +
onlineUser.CharacterNameHash))
{
_apiController.PromoteToModerator(onlineUser.UID);
}
}
else
{
if (ImGui.Button(FontAwesomeIcon.User.ToIconString() +
"##onlineUserNonModerator" +
onlineUser.CharacterNameHash))
{
_apiController.DemoteFromModerator(onlineUser.UID);
}
}
}
ImGui.PopFont();
}
ImGui.EndTable();
}
ImGui.TreePop();
}
}
private bool _deleteFilesPopupModalShown = false;
private bool _deleteAccountPopupModalShown = false;
private void DrawUserAdministration(bool serverAlive)
{
if (serverAlive)
{
if (ImGui.Button("Delete all my files"))
{
_deleteFilesPopupModalShown = true;
ImGui.OpenPopup("Delete all your files?");
}
UiShared.DrawHelpText("Completely deletes all your uploaded files on the service.");
if (ImGui.BeginPopupModal("Delete all your files?", ref _deleteFilesPopupModalShown,
ImGuiWindowFlags.AlwaysAutoResize))
{
UiShared.TextWrapped(
"All your own uploaded files on the service will be deleted.\nThis operation cannot be undone.");
ImGui.Text("Are you sure you want to continue?");
ImGui.Separator();
if (ImGui.Button("Delete everything", new Vector2(150, 0)))
{
Task.Run(() => _apiController.DeleteAllMyFiles());
ImGui.CloseCurrentPopup();
_deleteFilesPopupModalShown = false;
}
ImGui.SameLine();
if (ImGui.Button("Cancel##cancelDelete", new Vector2(150, 0)))
{
ImGui.CloseCurrentPopup();
_deleteFilesPopupModalShown = false;
}
ImGui.EndPopup();
}
if (ImGui.Button("Delete account"))
{
_deleteAccountPopupModalShown = true;
ImGui.OpenPopup("Delete your account?");
}
UiShared.DrawHelpText("Completely deletes your account and all uploaded files to the service.");
if (ImGui.BeginPopupModal("Delete your account?", ref _deleteAccountPopupModalShown,
ImGuiWindowFlags.AlwaysAutoResize))
{
UiShared.TextWrapped(
"Your account and all associated files and data on the service will be deleted.");
UiShared.TextWrapped("Your UID will be removed from all pairing lists.");
ImGui.Text("Are you sure you want to continue?");
ImGui.Separator();
if (ImGui.Button("Delete account", new Vector2(150, 0)))
{
Task.Run(() => _apiController.DeleteAccount());
ImGui.CloseCurrentPopup();
_deleteAccountPopupModalShown = false;
SwitchToIntroUi?.Invoke();
}
ImGui.SameLine();
if (ImGui.Button("Cancel##cancelDelete", new Vector2(150, 0)))
{
ImGui.CloseCurrentPopup();
_deleteAccountPopupModalShown = false;
}
ImGui.EndPopup();
}
}
if (!_configuration.FullPause)
{
UiShared.ColorTextWrapped("Note: to change servers you need to disconnect from your current Mare Synchronos server.", ImGuiColors.DalamudYellow);
}
var marePaused = _configuration.FullPause;
if (_configuration.HasValidSetup())
{
if (ImGui.Checkbox("Disconnect Mare Synchronos", ref marePaused))
{
_configuration.FullPause = marePaused;
_configuration.Save();
Task.Run(_apiController.CreateConnections);
}
UiShared.DrawHelpText("Completely pauses the sync and clears your current data (not uploaded files) on the service.");
}
else
{
UiShared.ColorText("You cannot reconnect without a valid account on the service.", ImGuiColors.DalamudYellow);
}
if (marePaused)
{
_uiShared.DrawServiceSelection(() => SwitchToIntroUi?.Invoke());
}
}
private void DrawBlockedTransfers()
{
UiShared.ColorTextWrapped("Files that you attempted to upload or download that were forbidden to be transferred by their creators will appear here. " +
"If you see file paths from your drive here, then those files were not allowed to be uploaded. If you see hashes, those files were not allowed to be downloaded. " +
"Ask your paired friend to send you the mod in question through other means, acquire the mod yourself or pester the mod creator to allow it to be sent over Mare.",
ImGuiColors.DalamudGrey);
if (ImGui.BeginTable("TransfersTable", 2, ImGuiTableFlags.SizingStretchProp))
{
ImGui.TableSetupColumn(
$"Hash/Filename");
ImGui.TableSetupColumn($"Forbidden by");
ImGui.TableHeadersRow();
foreach (var item in _apiController.ForbiddenTransfers)
{
ImGui.TableNextColumn();
if (item is UploadFileTransfer transfer)
{
ImGui.Text(transfer.LocalFile);
}
else
{
ImGui.Text(item.Hash);
}
ImGui.TableNextColumn();
ImGui.Text(item.ForbiddenBy);
}
ImGui.EndTable();
}
}
private void DrawCurrentTransfers()
{
bool showTransferWindow = _configuration.ShowTransferWindow;
if (ImGui.Checkbox("Show separate Transfer window while transfers are active", ref showTransferWindow))
{
_configuration.ShowTransferWindow = showTransferWindow;
_configuration.Save();
}
if (_configuration.ShowTransferWindow)
{
ImGui.Indent();
bool editTransferWindowPosition = _uiShared.EditTrackerPosition;
if (ImGui.Checkbox("Edit Transfer Window position", ref editTransferWindowPosition))
{
_uiShared.EditTrackerPosition = editTransferWindowPosition;
}
ImGui.Unindent();
}
if (ImGui.BeginTable("TransfersTable", 2))
{
ImGui.TableSetupColumn(
$"Uploads ({UiShared.ByteToString(_apiController.CurrentUploads.Sum(a => a.Transferred))} / {UiShared.ByteToString(_apiController.CurrentUploads.Sum(a => a.Total))})");
ImGui.TableSetupColumn($"Downloads ({UiShared.ByteToString(_apiController.CurrentDownloads.Sum(a => a.Transferred))} / {UiShared.ByteToString(_apiController.CurrentDownloads.Sum(a => a.Total))})");
ImGui.TableHeadersRow();
ImGui.TableNextColumn();
if (ImGui.BeginTable("UploadsTable", 3))
{
ImGui.TableSetupColumn("File");
ImGui.TableSetupColumn("Uploaded");
ImGui.TableSetupColumn("Size");
ImGui.TableHeadersRow();
foreach (var transfer in _apiController.CurrentUploads.ToArray())
{
var color = UiShared.UploadColor((transfer.Transferred, transfer.Total));
ImGui.PushStyleColor(ImGuiCol.Text, color);
ImGui.TableNextColumn();
ImGui.Text(transfer.Hash);
ImGui.TableNextColumn();
ImGui.Text(UiShared.ByteToString(transfer.Transferred));
ImGui.TableNextColumn();
ImGui.Text(UiShared.ByteToString(transfer.Total));
ImGui.PopStyleColor();
ImGui.TableNextRow();
}
ImGui.EndTable();
}
ImGui.TableNextColumn();
if (ImGui.BeginTable("DownloadsTable", 3))
{
ImGui.TableSetupColumn("File");
ImGui.TableSetupColumn("Downloaded");
ImGui.TableSetupColumn("Size");
ImGui.TableHeadersRow();
foreach (var transfer in _apiController.CurrentDownloads.ToArray())
{
var color = UiShared.UploadColor((transfer.Transferred, transfer.Total));
ImGui.PushStyleColor(ImGuiCol.Text, color);
ImGui.TableNextColumn();
ImGui.Text(transfer.Hash);
ImGui.TableNextColumn();
ImGui.Text(UiShared.ByteToString(transfer.Transferred));
ImGui.TableNextColumn();
ImGui.Text(UiShared.ByteToString(transfer.Total));
ImGui.PopStyleColor();
ImGui.TableNextRow();
}
ImGui.EndTable();
}
ImGui.EndTable();
}
}
private void DrawFileCacheSettings()
{
_uiShared.DrawFileScanState();
_uiShared.DrawCacheDirectorySetting();
ImGui.Text($"Local cache size: {UiShared.ByteToString(_uiShared.FileCacheSize)}");
ImGui.SameLine();
if (ImGui.Button("Clear local cache"))
{
Task.Run(() =>
{
foreach (var file in Directory.GetFiles(_configuration.CacheFolder))
{
File.Delete(file);
}
});
}
}
public override void OnClose()
{
_uiShared.EditTrackerPosition = false;
base.OnClose();
}
private string _tempNameUID = string.Empty;
}
}

View File

@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.ImGuiFileDialog;
using Dalamud.Plugin;
using ImGuiNET;
using MareSynchronos.Managers;
using MareSynchronos.Utils;
@@ -13,7 +14,7 @@ using MareSynchronos.WebAPI;
namespace MareSynchronos.UI
{
public class UiShared
public class UiShared : IDisposable
{
private readonly IpcManager _ipcManager;
private readonly ApiController _apiController;
@@ -21,12 +22,15 @@ namespace MareSynchronos.UI
private readonly FileDialogManager _fileDialogManager;
private readonly Configuration _pluginConfiguration;
private readonly DalamudUtil _dalamudUtil;
private readonly DalamudPluginInterface _pluginInterface;
public long FileCacheSize => _fileCacheManager.FileCacheSize;
public bool ShowClientSecret = true;
public string PlayerName => _dalamudUtil.PlayerName;
public bool EditTrackerPosition { get; set; }
public ImFontPtr UidFont { get; private set; }
public bool UidFontBuilt { get; private set; }
public UiShared(IpcManager ipcManager, ApiController apiController, FileCacheManager fileCacheManager, FileDialogManager fileDialogManager, Configuration pluginConfiguration, DalamudUtil dalamudUtil)
public UiShared(IpcManager ipcManager, ApiController apiController, FileCacheManager fileCacheManager, FileDialogManager fileDialogManager, Configuration pluginConfiguration, DalamudUtil dalamudUtil, DalamudPluginInterface pluginInterface)
{
_ipcManager = ipcManager;
_apiController = apiController;
@@ -34,7 +38,35 @@ namespace MareSynchronos.UI
_fileDialogManager = fileDialogManager;
_pluginConfiguration = pluginConfiguration;
_dalamudUtil = dalamudUtil;
_pluginInterface = pluginInterface;
_isDirectoryWritable = IsDirectoryWritable(_pluginConfiguration.CacheFolder);
_pluginInterface.UiBuilder.BuildFonts += BuildFont;
_pluginInterface.UiBuilder.RebuildFonts();
}
private void BuildFont()
{
var fontFile = Path.Combine(_pluginInterface.DalamudAssetDirectory.FullName, "UIRes", "NotoSansCJKjp-Medium.otf");
UidFontBuilt = false;
if (File.Exists(fontFile))
{
try
{
UidFont = ImGui.GetIO().Fonts.AddFontFromFileTTF(fontFile, 35);
UidFontBuilt = true;
}
catch (Exception ex)
{
Logger.Debug($"Font failed to load. {fontFile}");
Logger.Debug(ex.ToString());
}
}
else
{
Logger.Debug($"Font doesn't exist. {fontFile}");
}
}
public bool DrawOtherPluginState()
@@ -408,5 +440,10 @@ namespace MareSynchronos.UI
_pluginConfiguration.Save();
}
}
public void Dispose()
{
_pluginInterface.UiBuilder.BuildFonts -= BuildFont;
}
}
}