Skip to content

Commit

Permalink
Merge branch 'release/1.7.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
fmauNeko committed Jul 14, 2024
2 parents a929c39 + 32e8911 commit 9f64710
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 115 deletions.
127 changes: 80 additions & 47 deletions MarketBoardPlugin/GUI/MarketBoardWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ public class MarketBoardWindow : Window, IDisposable

private int lvlmin;
private int lastlvlmin;
private int lvlmax = 90;
private int lastlvlmax = 90;
private int lvlmax = 100;
private int lastlvlmax = 100;
private int itemCategory;
private int lastItemCategory;
private string[] categoryLabels = new[] { "All", "Weapons", "Equipments", "Others", "Furniture" };
Expand All @@ -92,9 +92,9 @@ public class MarketBoardWindow : Window, IDisposable

private int previousSelectedWorld = -1;

private MarketDataResponse marketData;
private MarketDataResponse? marketData;

private List<MarketDataResponse> marketBuffer;
private readonly List<MarketDataResponse?> marketBuffer;

private int selectedListing = -1;

Expand All @@ -106,6 +106,10 @@ public class MarketBoardWindow : Window, IDisposable

private List<KeyValuePair<ItemSearchCategory, List<Item>>> enumerableCategoriesAndItems;

private Task? currentRefreshTask;

private CancellationTokenSource? currentRefreshCancellationTokenSource;

/// <summary>
/// Initializes a new instance of the <see cref="MarketBoardWindow"/> class.
/// </summary>
Expand Down Expand Up @@ -330,7 +334,7 @@ void SelectClassJob(ClassJob classJob)
{
// If the category selected doesn't need an equip level -> reset to default
this.lvlmin = 0;
this.lvlmax = 90;
this.lvlmax = 100;
}
}

Expand Down Expand Up @@ -374,6 +378,18 @@ void SelectClassJob(ClassJob classJob)
{
this.ChangeSelectedItem(id, true);
}

if (ImGui.BeginPopupContextItem($"itemContextMenu{item.Name}"))
{
if (ImGui.Selectable("Remove from the favorites"))
{
this.plugin.Config.Favorites.Remove(item.RowId);
}

ImGui.EndPopup();
}

ImGui.OpenPopupOnItemClick($"itemContextMenu{item.Name}", ImGuiPopupFlags.MouseButtonRight);
}
}
else
Expand Down Expand Up @@ -807,7 +823,7 @@ void SelectClassJob(ClassJob classJob)
}
}

ImGui.SetCursorPosY(ImGui.GetWindowContentRegionMax().Y - ImGui.GetTextLineHeightWithSpacing());
ImGui.SetCursorPosY(ImGui.GetWindowContentRegionMax().Y - ImGui.GetFrameHeight());
if (ImGui.Button("Data provided by Universalis"))
{
var universalisUrl = "https://universalis.app";
Expand All @@ -829,7 +845,7 @@ void SelectClassJob(ClassJob classJob)
ImGui.PushStyleColor(ImGuiCol.ButtonActive, 0xDD000000 | buttonColor);
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, 0xAA000000 | buttonColor);

if (ImGui.Button(buttonText, new Vector2(120, 24)))
if (ImGui.Button(buttonText, new Vector2(120, 0)))
{
Utilities.OpenBrowser("https://ko-fi.com/fmauneko");
}
Expand Down Expand Up @@ -1091,62 +1107,73 @@ private void HandleHoveredItemChange(object sender, ulong itemId)

private void RefreshMarketData()
{
Task.Run(async () =>
if (this.currentRefreshTask?.Status != TaskStatus.RanToCompletion)
{
var cachedItem = this.marketBuffer.FirstOrDefault(data => data.ItemId == this.selectedItem.RowId, null);
if (cachedItem != null)
{
this.marketData = cachedItem;
}
this.plugin.Log.Debug("Cancelling previous refresh task.");
this.currentRefreshCancellationTokenSource?.Cancel();
}

this.currentRefreshCancellationTokenSource = new CancellationTokenSource();

if (cachedItem == null || this.selectedWorld != this.previousSelectedWorld || DateTimeOffset.Now.ToUnixTimeMilliseconds() - cachedItem.FetchTimestamp > this.plugin.Config.ItemRefreshTimeout)
this.currentRefreshTask = Task.Run(
async () =>
{
this.previousSelectedWorld = this.selectedWorld;
if (cachedItem == null)
var cachedItem = this.marketBuffer.FirstOrDefault(data => data?.ItemId == this.selectedItem.RowId, null);
if (cachedItem != null)
{
this.marketData = cachedItem;
}
if (cachedItem == null || this.selectedWorld != this.previousSelectedWorld || DateTimeOffset.Now.ToUnixTimeMilliseconds() - cachedItem.FetchTimestamp > this.plugin.Config.ItemRefreshTimeout)
{
if (this.marketData != null)
this.previousSelectedWorld = this.selectedWorld;
if (cachedItem == null)
{
this.marketBuffer.Add(this.marketData);
if (this.marketData != null)
{
this.marketBuffer.Add(this.marketData);
}
if (this.marketBuffer.Count > this.plugin.Config.MarketBufferSize)
{
this.marketBuffer.RemoveAt(0);
}
this.marketData = null;
}
if (this.marketBuffer.Count > this.plugin.Config.MarketBufferSize)
try
{
this.marketBuffer.RemoveAt(0);
this.marketData = await this.plugin.UniversalisClient
.GetMarketData(
this.selectedItem.RowId,
this.worldList[this.selectedWorld].Item1,
50,
this.currentRefreshCancellationTokenSource.Token)
.ConfigureAwait(false);
}
catch (AggregateException ae)
{
this.plugin.Log.Warning(ae, $"Failed to fetch market data for item {this.selectedItem.RowId} from Universalis.");
this.marketData = null;
}
foreach (var ex in ae.InnerExceptions)
{
this.plugin.Log.Warning(ex, "Inner exception");
}
try
{
this.marketData = await this.plugin.UniversalisClient
.GetMarketData(
this.selectedItem.RowId,
this.worldList[this.selectedWorld].Item1,
50,
CancellationToken.None)
.ConfigureAwait(false);
}
catch (AggregateException ae)
{
this.plugin.Log.Warning(ae, $"Failed to fetch market data for item {this.selectedItem.RowId} from Universalis.");
this.marketData = null;
}
foreach (var ex in ae.InnerExceptions)
if (cachedItem != null)
{
this.plugin.Log.Warning(ex, "Inner exception");
this.marketBuffer.Remove(cachedItem);
this.marketBuffer.Add(this.marketData);
}
this.marketData = null;
}
},
this.currentRefreshCancellationTokenSource.Token);

if (cachedItem != null)
{
this.marketBuffer.Remove(cachedItem);
this.marketBuffer.Add(this.marketData);
}
}
})
.ContinueWith(
this.currentRefreshTask.ContinueWith(
t =>
{
if (t.IsFaulted)
Expand All @@ -1158,6 +1185,12 @@ private void RefreshMarketData()
this.plugin.Log.Warning(ex, "Inner exception");
}
}
else if (t.IsCanceled)
{
this.plugin.Log.Debug("Market data refresh task was cancelled.");
}
this.currentRefreshCancellationTokenSource.Dispose();
},
TaskScheduler.Current);
}
Expand Down
33 changes: 9 additions & 24 deletions MarketBoardPlugin/Helpers/UniversalisClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace MarketBoardPlugin.Helpers
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -32,50 +33,34 @@ public class UniversalisClient(MBPlugin plugin)
/// <param name="historyCount">The number of historical entries to retrieve.</param>
/// <param name="cancellationToken">A cancellation token to cancel the operation.</param>
/// <returns>A <see cref="MarketDataResponse"/> object containing the retrieved market data, or null if the operation fails.</returns>
public async Task<MarketDataResponse> GetMarketData(uint itemId, string worldName, int historyCount, CancellationToken cancellationToken)
public async Task<MarketDataResponse?> GetMarketData(uint itemId, string worldName, int historyCount, CancellationToken cancellationToken)
{
var uriBuilder = new UriBuilder($"https://universalis.app/api/{worldName}/{itemId}?entries={historyCount}");

cancellationToken.ThrowIfCancellationRequested();

using var client = new HttpClient();

Stream res;
MarketDataResponse? res;

try
{
res = await client
.GetStreamAsync(uriBuilder.Uri, cancellationToken)
.GetFromJsonAsync<MarketDataResponse>(uriBuilder.Uri, cancellationToken)
.ConfigureAwait(false);
}
catch (HttpRequestException)
catch (HttpRequestException ex)
{
this.plugin.Log.Warning($"Failed to fetch market data for item {itemId} on world {worldName}.");
this.plugin.Log.Warning(ex, $"Failed to fetch market data for item {itemId} on world {worldName}.");
return null;
}

cancellationToken.ThrowIfCancellationRequested();

MarketDataResponse parsedRes;

try
{
parsedRes = await JsonSerializer
.DeserializeAsync<MarketDataResponse>(res, cancellationToken: cancellationToken)
.ConfigureAwait(false);
}
catch (JsonException)
{
this.plugin.Log.Warning($"Failed to parse market data for item {itemId} on world {worldName}.");
return null;
}

if (parsedRes != null)
if (res != null)
{
parsedRes.FetchTimestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
res.FetchTimestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
}

return parsedRes;
return res;
}
}
}
Loading

0 comments on commit 9f64710

Please sign in to comment.