183 lines
5.5 KiB
C#
183 lines
5.5 KiB
C#
using System.Collections.ObjectModel;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using Poe2Trade.Bot;
|
|
using Poe2Trade.Core;
|
|
using Serilog;
|
|
|
|
namespace Poe2Trade.Ui.ViewModels;
|
|
|
|
public class LogEntry
|
|
{
|
|
public string Time { get; init; } = "";
|
|
public string Level { get; init; } = "";
|
|
public string Message { get; init; } = "";
|
|
}
|
|
|
|
public partial class CellState : ObservableObject
|
|
{
|
|
[ObservableProperty] private bool _isOccupied;
|
|
[ObservableProperty] private bool _borderTop;
|
|
[ObservableProperty] private bool _borderBottom;
|
|
[ObservableProperty] private bool _borderLeft;
|
|
[ObservableProperty] private bool _borderRight;
|
|
}
|
|
|
|
public partial class MainWindowViewModel : ObservableObject
|
|
{
|
|
private readonly BotOrchestrator _bot;
|
|
|
|
[ObservableProperty]
|
|
private string _state = "Idle";
|
|
|
|
[ObservableProperty]
|
|
[NotifyPropertyChangedFor(nameof(PauseButtonText))]
|
|
private bool _isPaused;
|
|
|
|
[ObservableProperty]
|
|
[NotifyCanExecuteChangedFor(nameof(StartCommand))]
|
|
[NotifyCanExecuteChangedFor(nameof(PauseCommand))]
|
|
private bool _isStarted;
|
|
|
|
[ObservableProperty] private string _newUrl = "";
|
|
[ObservableProperty] private string _newLinkName = "";
|
|
[ObservableProperty] private LinkMode _newLinkMode = LinkMode.Live;
|
|
[ObservableProperty] private int _tradesCompleted;
|
|
[ObservableProperty] private int _tradesFailed;
|
|
[ObservableProperty] private int _activeLinksCount;
|
|
|
|
public static LinkMode[] LinkModes { get; } = [LinkMode.Live, LinkMode.Scrap];
|
|
|
|
public MainWindowViewModel(BotOrchestrator bot)
|
|
{
|
|
_bot = bot;
|
|
_isPaused = bot.IsPaused;
|
|
|
|
for (var i = 0; i < 60; i++)
|
|
InventoryCells.Add(new CellState());
|
|
|
|
bot.StatusUpdated += () =>
|
|
{
|
|
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
|
{
|
|
State = bot.State;
|
|
IsPaused = bot.IsPaused;
|
|
var status = bot.GetStatus();
|
|
TradesCompleted = status.TradesCompleted;
|
|
TradesFailed = status.TradesFailed;
|
|
ActiveLinksCount = status.Links.Count(l => l.Active);
|
|
OnPropertyChanged(nameof(Links));
|
|
UpdateInventoryGrid();
|
|
});
|
|
};
|
|
|
|
bot.LogMessage += (level, message) =>
|
|
{
|
|
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
|
{
|
|
Logs.Add(new LogEntry
|
|
{
|
|
Time = DateTime.Now.ToString("HH:mm:ss"),
|
|
Level = level.ToUpperInvariant(),
|
|
Message = message
|
|
});
|
|
if (Logs.Count > 500) Logs.RemoveAt(0);
|
|
});
|
|
};
|
|
}
|
|
|
|
public string PauseButtonText => IsPaused ? "Resume" : "Pause";
|
|
public List<TradeLink> Links => _bot.Links.GetLinks();
|
|
public ObservableCollection<LogEntry> Logs { get; } = [];
|
|
public ObservableCollection<CellState> InventoryCells { get; } = [];
|
|
public int InventoryFreeCells => _bot.IsReady ? _bot.Inventory.Tracker.FreeCells : 60;
|
|
|
|
// Sub-ViewModels for tabs
|
|
public DebugViewModel? DebugVm { get; set; }
|
|
public SettingsViewModel? SettingsVm { get; set; }
|
|
|
|
[RelayCommand(CanExecute = nameof(CanStart))]
|
|
private async Task Start()
|
|
{
|
|
try
|
|
{
|
|
await _bot.Start([]);
|
|
IsStarted = true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Failed to start bot");
|
|
Logs.Add(new LogEntry
|
|
{
|
|
Time = DateTime.Now.ToString("HH:mm:ss"),
|
|
Level = "ERROR",
|
|
Message = $"Start failed: {ex.Message}"
|
|
});
|
|
}
|
|
}
|
|
private bool CanStart() => !IsStarted;
|
|
|
|
[RelayCommand(CanExecute = nameof(CanPause))]
|
|
private void Pause()
|
|
{
|
|
if (_bot.IsPaused) _bot.Resume();
|
|
else _bot.Pause();
|
|
}
|
|
private bool CanPause() => IsStarted;
|
|
|
|
[RelayCommand]
|
|
private void AddLink()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(NewUrl)) return;
|
|
_bot.AddLink(NewUrl, NewLinkName, NewLinkMode);
|
|
NewUrl = "";
|
|
NewLinkName = "";
|
|
}
|
|
|
|
[RelayCommand]
|
|
private void RemoveLink(string? id)
|
|
{
|
|
if (id != null) _bot.RemoveLink(id);
|
|
}
|
|
|
|
[RelayCommand]
|
|
private void ToggleLink(string? id)
|
|
{
|
|
if (id == null) return;
|
|
var link = _bot.Links.GetLink(id);
|
|
if (link != null) _bot.ToggleLink(id, !link.Active);
|
|
}
|
|
|
|
private void UpdateInventoryGrid()
|
|
{
|
|
if (!_bot.IsReady) return;
|
|
var (grid, items, _) = _bot.Inventory.GetInventoryState();
|
|
|
|
for (var r = 0; r < 5; r++)
|
|
for (var c = 0; c < 12; c++)
|
|
{
|
|
var cell = InventoryCells[r * 12 + c];
|
|
cell.IsOccupied = grid[r, c];
|
|
cell.BorderTop = false;
|
|
cell.BorderBottom = false;
|
|
cell.BorderLeft = false;
|
|
cell.BorderRight = false;
|
|
}
|
|
|
|
foreach (var item in items)
|
|
{
|
|
for (var r = item.Row; r < item.Row + item.H; r++)
|
|
for (var c = item.Col; c < item.Col + item.W; c++)
|
|
{
|
|
if (r >= 5 || c >= 12) continue;
|
|
var cell = InventoryCells[r * 12 + c];
|
|
if (r == item.Row) cell.BorderTop = true;
|
|
if (r == item.Row + item.H - 1) cell.BorderBottom = true;
|
|
if (c == item.Col) cell.BorderLeft = true;
|
|
if (c == item.Col + item.W - 1) cell.BorderRight = true;
|
|
}
|
|
}
|
|
|
|
OnPropertyChanged(nameof(InventoryFreeCells));
|
|
}
|
|
}
|