Update 0.1.4 - AutoDetect WIP Debug & Fix UI & Optimization
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<AssemblyName>UmbraSync</AssemblyName>
|
||||
<RootNamespace>UmbraSync</RootNamespace>
|
||||
<Version>0.1.2.0</Version>
|
||||
<Version>0.1.4.1</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -100,6 +100,7 @@ public sealed class Plugin : IDalamudPlugin
|
||||
collection.AddSingleton<MareSynchronos.WebAPI.AutoDetect.DiscoveryApiClient>();
|
||||
collection.AddSingleton<MareSynchronos.Services.AutoDetect.AutoDetectRequestService>();
|
||||
collection.AddSingleton<MareSynchronos.Services.AutoDetect.NearbyDiscoveryService>();
|
||||
collection.AddSingleton<MareSynchronos.Services.AutoDetect.NearbyPendingService>();
|
||||
collection.AddSingleton<MarePlugin>();
|
||||
collection.AddSingleton<MareProfileManager>();
|
||||
collection.AddSingleton<GameObjectHandlerFactory>();
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MareSynchronos.WebAPI.AutoDetect;
|
||||
using MareSynchronos.MareConfiguration;
|
||||
using MareSynchronos.Services;
|
||||
using MareSynchronos.Services.Mediator;
|
||||
using NotificationType = MareSynchronos.MareConfiguration.Models.NotificationType;
|
||||
|
||||
namespace MareSynchronos.Services.AutoDetect;
|
||||
|
||||
@@ -10,13 +13,17 @@ public class AutoDetectRequestService
|
||||
private readonly DiscoveryConfigProvider _configProvider;
|
||||
private readonly DiscoveryApiClient _client;
|
||||
private readonly MareConfigService _configService;
|
||||
private readonly DalamudUtilService _dalamud;
|
||||
private readonly MareMediator _mediator;
|
||||
|
||||
public AutoDetectRequestService(ILogger<AutoDetectRequestService> logger, DiscoveryConfigProvider configProvider, DiscoveryApiClient client, MareConfigService configService)
|
||||
public AutoDetectRequestService(ILogger<AutoDetectRequestService> logger, DiscoveryConfigProvider configProvider, DiscoveryApiClient client, MareConfigService configService, MareMediator mediator, DalamudUtilService dalamudUtilService)
|
||||
{
|
||||
_logger = logger;
|
||||
_configProvider = configProvider;
|
||||
_client = client;
|
||||
_configService = configService;
|
||||
_mediator = mediator;
|
||||
_dalamud = dalamudUtilService;
|
||||
}
|
||||
|
||||
public async Task<bool> SendRequestAsync(string token, CancellationToken ct = default)
|
||||
@@ -24,14 +31,34 @@ public class AutoDetectRequestService
|
||||
if (!_configService.Current.AllowAutoDetectPairRequests)
|
||||
{
|
||||
_logger.LogDebug("Nearby request blocked: AllowAutoDetectPairRequests is disabled");
|
||||
_mediator.Publish(new NotificationMessage("Nearby request blocked", "Enable 'Allow pair requests' in Settings to send requests.", NotificationType.Info));
|
||||
return false;
|
||||
}
|
||||
var endpoint = _configProvider.RequestEndpoint;
|
||||
if (string.IsNullOrEmpty(endpoint))
|
||||
{
|
||||
_logger.LogDebug("No request endpoint configured");
|
||||
_mediator.Publish(new NotificationMessage("Nearby request failed", "Server does not expose request endpoint.", NotificationType.Error));
|
||||
return false;
|
||||
}
|
||||
return await _client.SendRequestAsync(endpoint!, token, ct).ConfigureAwait(false);
|
||||
string? displayName = null;
|
||||
try
|
||||
{
|
||||
var me = await _dalamud.RunOnFrameworkThread(() => _dalamud.GetPlayerCharacter()).ConfigureAwait(false);
|
||||
displayName = me?.Name.TextValue;
|
||||
}
|
||||
catch { }
|
||||
|
||||
_logger.LogInformation("Nearby: sending pair request via {endpoint}", endpoint);
|
||||
var ok = await _client.SendRequestAsync(endpoint!, token, displayName, ct).ConfigureAwait(false);
|
||||
if (ok)
|
||||
{
|
||||
_mediator.Publish(new NotificationMessage("Nearby request sent", "The other user will receive a request notification.", NotificationType.Info));
|
||||
}
|
||||
else
|
||||
{
|
||||
_mediator.Publish(new NotificationMessage("Nearby request failed", "The server rejected the request. Try again soon.", NotificationType.Warning));
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class DiscoveryConfigProvider
|
||||
root.NearbyDiscovery?.Hydrate();
|
||||
_config = root;
|
||||
_lastLoad = DateTimeOffset.UtcNow;
|
||||
_logger.LogDebug("Loaded Nearby well-known (stapled), enabled={enabled}", NearbyEnabled);
|
||||
_logger.LogInformation("Loaded Nearby well-known (stapled), enabled={enabled}, expires={exp}", NearbyEnabled, _config?.NearbyDiscovery?.SaltExpiresAt);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -25,6 +25,9 @@ public class NearbyDiscoveryService : IHostedService, IMediatorSubscriber
|
||||
private bool _loggedLocalOnly;
|
||||
private int _lastLocalCount = -1;
|
||||
private int _lastMatchCount = -1;
|
||||
private bool _loggedConfigReady;
|
||||
private string? _lastSnapshotSig;
|
||||
private volatile bool _isConnected;
|
||||
|
||||
public NearbyDiscoveryService(ILogger<NearbyDiscoveryService> logger, MareMediator mediator,
|
||||
MareConfigService config, DiscoveryConfigProvider configProvider, DalamudUtilService dalamudUtilService,
|
||||
@@ -44,7 +47,8 @@ public class NearbyDiscoveryService : IHostedService, IMediatorSubscriber
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_loopCts = new CancellationTokenSource();
|
||||
_mediator.Subscribe<ConnectedMessage>(this, _ => _configProvider.TryLoadFromStapled());
|
||||
_mediator.Subscribe<ConnectedMessage>(this, _ => { _isConnected = true; _configProvider.TryLoadFromStapled(); });
|
||||
_mediator.Subscribe<DisconnectedMessage>(this, _ => { _isConnected = false; _lastPublishedSignature = null; });
|
||||
_ = Task.Run(() => Loop(_loopCts.Token));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
@@ -65,7 +69,7 @@ public class NearbyDiscoveryService : IHostedService, IMediatorSubscriber
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_config.Current.EnableAutoDetectDiscovery || !_dalamud.IsLoggedIn)
|
||||
if (!_config.Current.EnableAutoDetectDiscovery || !_dalamud.IsLoggedIn || !_isConnected)
|
||||
{
|
||||
await Task.Delay(1000, ct).ConfigureAwait(false);
|
||||
continue;
|
||||
@@ -79,6 +83,11 @@ public class NearbyDiscoveryService : IHostedService, IMediatorSubscriber
|
||||
await _configProvider.TryFetchFromServerAsync(ct).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else if (!_loggedConfigReady && _configProvider.NearbyEnabled)
|
||||
{
|
||||
_loggedConfigReady = true;
|
||||
_logger.LogInformation("Nearby: well-known loaded and enabled; refresh={refresh}s, expires={exp}", _configProvider.RefreshSec, _configProvider.SaltExpiresAt);
|
||||
}
|
||||
|
||||
var entries = await GetLocalNearbyAsync().ConfigureAwait(false);
|
||||
// Log when local count changes (including 0) to indicate activity
|
||||
@@ -95,7 +104,7 @@ public class NearbyDiscoveryService : IHostedService, IMediatorSubscriber
|
||||
try
|
||||
{
|
||||
var saltHex = Convert.ToHexString(_configProvider.Salt!);
|
||||
// map hash->index for result matching and reuse for publish
|
||||
// map hash->index for result matching
|
||||
Dictionary<string, int> hashToIndex = new(StringComparer.Ordinal);
|
||||
List<string> hashes = new(entries.Count);
|
||||
foreach (var (entry, idx) in entries.Select((e, i) => (e, i)))
|
||||
@@ -105,35 +114,63 @@ public class NearbyDiscoveryService : IHostedService, IMediatorSubscriber
|
||||
hashes.Add(h);
|
||||
}
|
||||
|
||||
// Publish local snapshot if endpoint is available (deduplicated)
|
||||
// Debug snapshot once per change
|
||||
try
|
||||
{
|
||||
var snapSig = string.Join(',', hashes.OrderBy(s => s, StringComparer.Ordinal)).GetHash256();
|
||||
if (!string.Equals(snapSig, _lastSnapshotSig, StringComparison.Ordinal))
|
||||
{
|
||||
_lastSnapshotSig = snapSig;
|
||||
var sample = entries.Take(5).Select(e =>
|
||||
{
|
||||
var hh = (saltHex + e.Name + e.WorldId.ToString()).GetHash256();
|
||||
var shortH = hh.Length > 8 ? hh[..8] : hh;
|
||||
return $"{e.Name}({e.WorldId})->{shortH}";
|
||||
});
|
||||
var saltShort = saltHex.Length > 8 ? saltHex[..8] : saltHex;
|
||||
_logger.LogInformation("Nearby snapshot: {count} entries; salt={saltShort}…; samples=[{samples}]",
|
||||
entries.Count, saltShort, string.Join(", ", sample));
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Publish OUR presence (own hash) if endpoint is available (deduplicated)
|
||||
if (!string.IsNullOrEmpty(_configProvider.PublishEndpoint))
|
||||
{
|
||||
string? displayName = null;
|
||||
string? selfHash = null;
|
||||
try
|
||||
{
|
||||
var me = await _dalamud.RunOnFrameworkThread(() => _dalamud.GetPlayerCharacter()).ConfigureAwait(false);
|
||||
if (me != null)
|
||||
{
|
||||
displayName = me.Name.TextValue;
|
||||
ushort meWorld = 0;
|
||||
if (me is Dalamud.Game.ClientState.Objects.SubKinds.IPlayerCharacter mePc)
|
||||
meWorld = (ushort)mePc.HomeWorld.RowId;
|
||||
_logger.LogInformation("Nearby self ident: {name} ({world})", displayName, meWorld);
|
||||
selfHash = (saltHex + displayName + meWorld.ToString()).GetHash256();
|
||||
}
|
||||
}
|
||||
catch { /* ignore */ }
|
||||
|
||||
if (hashes.Count > 0)
|
||||
if (!string.IsNullOrEmpty(selfHash))
|
||||
{
|
||||
var sig = string.Join(',', hashes.OrderBy(s => s, StringComparer.Ordinal)).GetHash256();
|
||||
var sig = selfHash!;
|
||||
if (!string.Equals(sig, _lastPublishedSignature, StringComparison.Ordinal))
|
||||
{
|
||||
_lastPublishedSignature = sig;
|
||||
_logger.LogDebug("Nearby publish: {count} hashes (updated)", hashes.Count);
|
||||
_ = _api.PublishAsync(_configProvider.PublishEndpoint!, hashes, displayName, ct);
|
||||
var shortSelf = selfHash!.Length > 8 ? selfHash[..8] : selfHash;
|
||||
_logger.LogInformation("Nearby publish: self presence updated (hash={hash})", shortSelf);
|
||||
var ok = await _api.PublishAsync(_configProvider.PublishEndpoint!, new[] { selfHash! }, displayName, ct).ConfigureAwait(false);
|
||||
_logger.LogInformation("Nearby publish result: {result}", ok ? "success" : "failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogDebug("Nearby publish skipped (no changes)");
|
||||
}
|
||||
}
|
||||
// else: no local entries; skip publish silently
|
||||
// else: no self character available; skip publish silently
|
||||
}
|
||||
|
||||
// Query for matches if endpoint is available
|
||||
@@ -160,6 +197,7 @@ public class NearbyDiscoveryService : IHostedService, IMediatorSubscriber
|
||||
}
|
||||
}
|
||||
}
|
||||
_logger.LogInformation("Nearby: server returned {count} matches", allMatches.Count);
|
||||
|
||||
// Log change in number of Umbra matches
|
||||
int matchCount = entries.Count(e => e.IsMatch);
|
||||
@@ -206,7 +244,8 @@ public class NearbyDiscoveryService : IHostedService, IMediatorSubscriber
|
||||
var localPos = local?.Position ?? Vector3.Zero;
|
||||
int maxDist = Math.Clamp(_config.Current.AutoDetectMaxDistanceMeters, 5, 100);
|
||||
|
||||
for (int i = 0; i < 200; i += 2)
|
||||
int limit = Math.Min(200, _objectTable.Length);
|
||||
for (int i = 0; i < limit; i++)
|
||||
{
|
||||
var obj = await _dalamud.RunOnFrameworkThread(() => _objectTable[i]).ConfigureAwait(false);
|
||||
if (obj == null || obj.ObjectKind != Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player) continue;
|
||||
@@ -215,7 +254,7 @@ public class NearbyDiscoveryService : IHostedService, IMediatorSubscriber
|
||||
float dist = local == null ? float.NaN : Vector3.Distance(localPos, obj.Position);
|
||||
if (!float.IsNaN(dist) && dist > maxDist) continue;
|
||||
|
||||
string name = obj.Name.ToString();
|
||||
string name = obj.Name.TextValue;
|
||||
ushort worldId = 0;
|
||||
if (obj is Dalamud.Game.ClientState.Objects.SubKinds.IPlayerCharacter pc)
|
||||
worldId = (ushort)pc.HomeWorld.RowId;
|
||||
|
||||
70
MareSynchronos/Services/AutoDetect/NearbyPendingService.cs
Normal file
70
MareSynchronos/Services/AutoDetect/NearbyPendingService.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text.RegularExpressions;
|
||||
using MareSynchronos.Services.Mediator;
|
||||
using MareSynchronos.WebAPI;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace MareSynchronos.Services.AutoDetect;
|
||||
|
||||
public sealed class NearbyPendingService : IMediatorSubscriber
|
||||
{
|
||||
private readonly ILogger<NearbyPendingService> _logger;
|
||||
private readonly MareMediator _mediator;
|
||||
private readonly ApiController _api;
|
||||
private readonly ConcurrentDictionary<string, string> _pending = new(StringComparer.Ordinal);
|
||||
private static readonly Regex ReqRegex = new(@"^Nearby Request: (.+) \[(?<uid>[A-Z0-9]+)\]$", RegexOptions.Compiled);
|
||||
|
||||
public NearbyPendingService(ILogger<NearbyPendingService> logger, MareMediator mediator, ApiController api)
|
||||
{
|
||||
_logger = logger;
|
||||
_mediator = mediator;
|
||||
_api = api;
|
||||
_mediator.Subscribe<NotificationMessage>(this, OnNotification);
|
||||
}
|
||||
|
||||
public MareMediator Mediator => _mediator;
|
||||
|
||||
public IReadOnlyDictionary<string, string> Pending => _pending;
|
||||
|
||||
private void OnNotification(NotificationMessage msg)
|
||||
{
|
||||
// Watch info messages for Nearby request pattern
|
||||
if (msg.Type != MareSynchronos.MareConfiguration.Models.NotificationType.Info) return;
|
||||
var m = ReqRegex.Match(msg.Message);
|
||||
if (!m.Success) return;
|
||||
var uid = m.Groups["uid"].Value;
|
||||
if (string.IsNullOrEmpty(uid)) return;
|
||||
// Try to extract name as everything before space and '['
|
||||
var name = msg.Message;
|
||||
try
|
||||
{
|
||||
var idx = msg.Message.IndexOf(':');
|
||||
if (idx >= 0) name = msg.Message[(idx + 1)..].Trim();
|
||||
var br = name.LastIndexOf('[');
|
||||
if (br > 0) name = name[..br].Trim();
|
||||
}
|
||||
catch { name = uid; }
|
||||
_pending[uid] = name;
|
||||
_logger.LogInformation("NearbyPending: received request from {uid} ({name})", uid, name);
|
||||
}
|
||||
|
||||
public void Remove(string uid)
|
||||
{
|
||||
_pending.TryRemove(uid, out _);
|
||||
}
|
||||
|
||||
public async Task<bool> AcceptAsync(string uid)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _api.UserAddPair(new MareSynchronos.API.Dto.User.UserDto(new MareSynchronos.API.Data.UserData(uid))).ConfigureAwait(false);
|
||||
_pending.TryRemove(uid, out _);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "NearbyPending: accept failed for {uid}", uid);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
private readonly ServerConfigurationManager _serverManager;
|
||||
private readonly Stopwatch _timeout = new();
|
||||
private readonly CharaDataManager _charaDataManager;
|
||||
private readonly Services.AutoDetect.NearbyPendingService _nearbyPending;
|
||||
private readonly UidDisplayHandler _uidDisplayHandler;
|
||||
private readonly UiSharedService _uiSharedService;
|
||||
private bool _buttonState;
|
||||
@@ -62,6 +63,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
|
||||
public CompactUi(ILogger<CompactUi> logger, UiSharedService uiShared, MareConfigService configService, ApiController apiController, PairManager pairManager, ChatService chatService,
|
||||
ServerConfigurationManager serverManager, MareMediator mediator, FileUploadManager fileTransferManager, UidDisplayHandler uidDisplayHandler, CharaDataManager charaDataManager,
|
||||
Services.AutoDetect.NearbyPendingService nearbyPendingService,
|
||||
PerformanceCollectorService performanceCollectorService)
|
||||
: base(logger, mediator, "###UmbraSyncMainUI", performanceCollectorService)
|
||||
{
|
||||
@@ -73,6 +75,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
_fileTransferManager = fileTransferManager;
|
||||
_uidDisplayHandler = uidDisplayHandler;
|
||||
_charaDataManager = charaDataManager;
|
||||
_nearbyPending = nearbyPendingService;
|
||||
var tagHandler = new TagHandler(_serverManager);
|
||||
|
||||
_groupPanel = new(this, uiShared, _pairManager, chatService, uidDisplayHandler, _configService, _serverManager, _charaDataManager);
|
||||
@@ -180,14 +183,6 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
ImGui.Separator();
|
||||
using (ImRaii.PushId("transfers")) DrawTransfers();
|
||||
using (ImRaii.PushId("autosync"))
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.UserPlus, "Nearby", (WindowContentWidth - ImGui.GetStyle().ItemSpacing.X) / 2))
|
||||
{
|
||||
Mediator.Publish(new UiToggleMessage(typeof(AutoDetectUi)));
|
||||
}
|
||||
}
|
||||
TransferPartHeight = ImGui.GetCursorPosY() - TransferPartHeight;
|
||||
using (ImRaii.PushId("group-user-popup")) _selectPairsForGroupUi.Draw(_pairManager.DirectPairs);
|
||||
using (ImRaii.PushId("grouping-popup")) _selectGroupForPairUi.Draw();
|
||||
@@ -396,6 +391,16 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
: $"Nearby ({nearbyCount} Players)");
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) _nearbyOpen = !_nearbyOpen;
|
||||
|
||||
// Header action button to open Nearby window
|
||||
var btnWidth = _uiSharedService.GetIconTextButtonSize(FontAwesomeIcon.UserPlus, "Nearby");
|
||||
var headerRight = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth();
|
||||
ImGui.SameLine();
|
||||
ImGui.SetCursorPosX(headerRight - btnWidth);
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.UserPlus, "Nearby", btnWidth))
|
||||
{
|
||||
Mediator.Publish(new UiToggleMessage(typeof(AutoDetectUi)));
|
||||
}
|
||||
|
||||
if (_nearbyOpen)
|
||||
{
|
||||
ImGui.Indent();
|
||||
@@ -407,6 +412,34 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("Open Nearby for details.", ImGuiColors.DalamudGrey3);
|
||||
}
|
||||
// Pending Nearby requests (Accept / Dismiss)
|
||||
try
|
||||
{
|
||||
var inbox = _nearbyPending;
|
||||
if (inbox != null && inbox.Pending.Count > 0)
|
||||
{
|
||||
ImGuiHelpers.ScaledDummy(6);
|
||||
_uiSharedService.BigText("Requests");
|
||||
foreach (var kv in inbox.Pending)
|
||||
{
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted($"{kv.Value} [{kv.Key}]");
|
||||
ImGui.SameLine();
|
||||
if (_uiSharedService.IconButton(FontAwesomeIcon.Check))
|
||||
{
|
||||
_ = inbox.AcceptAsync(kv.Key);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Accept and add as pair");
|
||||
ImGui.SameLine();
|
||||
if (_uiSharedService.IconButton(FontAwesomeIcon.Times))
|
||||
{
|
||||
inbox.Remove(kv.Key);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Dismiss request");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
ImGui.Unindent();
|
||||
ImGui.Separator();
|
||||
}
|
||||
@@ -530,21 +563,20 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
ImGui.TextUnformatted(downloadText);
|
||||
}
|
||||
|
||||
var bottomButtonWidth = (WindowContentWidth - ImGui.GetStyle().ItemSpacing.X) / 2;
|
||||
|
||||
// Space for three equal-width buttons laid out precisely (avoid overlap/wrap)
|
||||
var spacing = ImGui.GetStyle().ItemSpacing.X;
|
||||
var bottomButtonWidth = (WindowContentWidth - spacing) / 2f;
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.PersonCircleQuestion, "Character Analysis", bottomButtonWidth))
|
||||
{
|
||||
Mediator.Publish(new UiToggleMessage(typeof(DataAnalysisUi)));
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Running, "Character Data Hub", bottomButtonWidth))
|
||||
{
|
||||
Mediator.Publish(new UiToggleMessage(typeof(CharaDataHubUi)));
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGuiHelpers.ScaledDummy(2);
|
||||
}
|
||||
|
||||
private void DrawUIDHeader()
|
||||
|
||||
@@ -212,7 +212,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
_uiShared.BigText("Nearby");
|
||||
_uiShared.BigText("AutoDetect");
|
||||
bool enableDiscovery = _configService.Current.EnableAutoDetectDiscovery;
|
||||
if (ImGui.Checkbox("Enable Nearby detection (beta)", ref enableDiscovery))
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"Tags": [
|
||||
"customization"
|
||||
],
|
||||
"IconUrl": "https://repo.umbra-sync.net/logo.png",
|
||||
"IconUrl": "https://repo.umbra-sync.net/images/logo.png",
|
||||
"RepoUrl": "https://repo.umbra-sync.net/plugin.json",
|
||||
"CanUnloadAsync": true
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ public class DiscoveryApiClient
|
||||
private readonly ILogger<DiscoveryApiClient> _logger;
|
||||
private readonly TokenProvider _tokenProvider;
|
||||
private readonly HttpClient _httpClient = new();
|
||||
private static readonly JsonSerializerOptions JsonOpt = new() { PropertyNameCaseInsensitive = true };
|
||||
|
||||
public DiscoveryApiClient(ILogger<DiscoveryApiClient> logger, TokenProvider tokenProvider)
|
||||
{
|
||||
@@ -32,7 +33,7 @@ public class DiscoveryApiClient
|
||||
var resp = await _httpClient.SendAsync(req, ct).ConfigureAwait(false);
|
||||
resp.EnsureSuccessStatusCode();
|
||||
var json = await resp.Content.ReadAsStringAsync(ct).ConfigureAwait(false);
|
||||
var result = JsonSerializer.Deserialize<List<ServerMatch>>(json) ?? [];
|
||||
var result = JsonSerializer.Deserialize<List<ServerMatch>>(json, JsonOpt) ?? [];
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -42,7 +43,7 @@ public class DiscoveryApiClient
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> SendRequestAsync(string endpoint, string token, CancellationToken ct)
|
||||
public async Task<bool> SendRequestAsync(string endpoint, string token, string? displayName, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -50,10 +51,17 @@ public class DiscoveryApiClient
|
||||
if (string.IsNullOrEmpty(jwt)) return false;
|
||||
using var req = new HttpRequestMessage(HttpMethod.Post, endpoint);
|
||||
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", jwt);
|
||||
var body = JsonSerializer.Serialize(new { token });
|
||||
var body = JsonSerializer.Serialize(new { token, displayName });
|
||||
req.Content = new StringContent(body, Encoding.UTF8, "application/json");
|
||||
var resp = await _httpClient.SendAsync(req, ct).ConfigureAwait(false);
|
||||
return resp.IsSuccessStatusCode;
|
||||
if (!resp.IsSuccessStatusCode)
|
||||
{
|
||||
string txt = string.Empty;
|
||||
try { txt = await resp.Content.ReadAsStringAsync(ct).ConfigureAwait(false); } catch { }
|
||||
_logger.LogWarning("Discovery request failed: {code} {reason} {body}", (int)resp.StatusCode, resp.ReasonPhrase, txt);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user