using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using XFEEDToolBox.Services;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Galaxy;
using XFEEDToolBox.Core.Presentation;
namespace XFEEDToolBox.ViewModels;
public partial class ToolboxViewModel
{
private readonly LocalUserProfile localProfile=LocalUserProfile.Read();
[ObservableProperty] public partial string ProfileDisplayName { get; set; } = "指挥官";
[ObservableProperty] public partial string ProfileNameOverride { get; set; } = "";
[ObservableProperty] public partial string ProfileAvatarPath { get; set; } = "";
[ObservableProperty] public partial ImageSource? ProfileAvatar { get; set; }
[ObservableProperty] public partial string ProfileStatus { get; set; } = "头像读取本机缓存,可在这里自定义。";
[ObservableProperty] public partial string ProfileCommanderId{get;set;}="未读取";
[ObservableProperty] public partial string ProfileCommanderName{get;set;}="等待指挥官档案";
[ObservableProperty] public partial string ProfileArxText{get;set;}="未读取";
[ObservableProperty] public partial string ProfileArxNote{get;set;}="等待游戏钱包数据";
[ObservableProperty] public partial string ProfileExplorationSummary{get;set;}="等待探索记录";
[ObservableProperty] public partial string ProfileVisitedCount{get;set;}="—";
[ObservableProperty] public partial string ProfileScannedCount{get;set;}="—";
[ObservableProperty] public partial string ProfileStatisticsTime{get;set;}="等待游戏统计";
[ObservableProperty] public partial IReadOnlyList<CommanderMetric> ProfileStatistics{get;set;}=[];
[ObservableProperty] public partial IReadOnlyList<CommanderMetric> ProfileRanks{get;set;}=[];
[ObservableProperty] public partial IReadOnlyList<GalacticSystem> ProfileExploredSystems{get;set;}=[];
[ObservableProperty] public partial IReadOnlyList<VisitedSystem> ProfileRecentVisits{get;set;}=[];
[ObservableProperty] public partial Coordinates ProfileMapCentre{get;set;}=new(0,0,0);
private IReadOnlyList<VisitedSystem>? profileMapSource;
private readonly Core.Native.ReadOnlyWalletReader walletReader=new();
private Microsoft.UI.Dispatching.DispatcherQueueTimer? walletTimer;
private bool readingWallet;
private Core.Native.GameWalletSnapshot? walletSnapshot;
private string walletOwner="";
public Core.Native.GameWalletSnapshot? WalletSnapshot=>walletSnapshot;
public async Task RefreshWalletAsync()
{
if(Environment.GetCommandLineArgs().Contains("--smoke-interface"))return;
if(readingWallet||lifetime.IsCancellationRequested)return;
readingWallet=true;
try
{
var snapshot=await Task.Run(walletReader.Read,lifetime.Token);
var player=CurrentPlayer;
if(player.CommanderId.Length==0||player.LoadGameAt is not {} loaded||loaded.UtcTicks<snapshot.StartedUtcTicks-TimeSpan.FromSeconds(5).Ticks)throw new InvalidOperationException("等待当前游戏的指挥官档案");
walletSnapshot=snapshot;walletOwner=player.CommanderId;ProfileArxText=snapshot.Arx.ToString("N0");ProfileArxNote=$"游戏钱包 · 本机读取 {snapshot.ReadAt.ToLocalTime():HH:mm:ss}";
}
catch(Exception error)when(error is not OperationCanceledException){walletSnapshot=null;ProfileArxText="未读取";ProfileArxNote=error.Message;}
finally{readingWallet=false;}
}
private void RefreshProfileData(PlayerState player)
{
ProfileCommanderId=player.CommanderId.Length>0?player.CommanderId:"未读取";
ProfileCommanderName=player.Commander.Length>0?"CMDR "+player.Commander:"等待指挥官档案";
var data=player.Profile;
if(walletOwner!=player.CommanderId)walletSnapshot=null;
if(walletSnapshot is null){ProfileArxText=data.Arx?.ToString("N0")??"未读取";ProfileArxNote=data.ArxAt is {} at?$"钱包更新 {at.ToLocalTime():MM-dd HH:mm:ss}":"等待游戏钱包数据";}
ProfileStatistics=StableSequence(ProfileStatistics,data.Statistics);ProfileRanks=StableSequence(ProfileRanks,data.Ranks);
ProfileStatisticsTime=data.StatisticsAt is {} stats?$"游戏统计 · {stats.ToLocalTime():MM-dd HH:mm:ss}":"等待游戏统计快照";
ProfileVisitedCount=data.VisitedSystems.Count.ToString("N0");ProfileScannedCount=data.ScannedBodies.ToString("N0");
ProfileExplorationSummary=$"本机已记录 {data.VisitedSystems.Count:N0} 个访问星系 · {data.ScannedBodies:N0} 个扫描天体 · 首次发现 {data.FirstDiscoveredBodies:N0}\n本机 Journal 覆盖范围内的航迹;累计统计以游戏统计快照为准。";
if(!ReferenceEquals(profileMapSource,data.VisitedSystems))
{
profileMapSource=data.VisitedSystems;
ProfileExploredSystems=data.VisitedSystems.Select(v=>new GalacticSystem(v.Name,v.Position,v.SystemAddress,v.StarClass,"指挥官访问记录")).ToArray();
ProfileRecentVisits=data.VisitedSystems.Take(100).ToArray();
}
if(player.Position is {} position)ProfileMapCentre=position;
}
private void InitializeProfile()
{
ProfileNameOverride=runtime.Settings.ProfileDisplayName;ProfileAvatarPath=runtime.Settings.ProfileAvatarPath;
RefreshProfileName();LoadProfileAvatar();
walletTimer=dispatcher.CreateTimer();walletTimer.Interval=TimeSpan.FromSeconds(5);walletTimer.Tick+=async(_,_)=>{if(initialized)await RefreshWalletAsync();};walletTimer.Start();
}
private void RefreshProfileName()=>ProfileDisplayName=ProfileNameOverride.Trim().Length>0?ProfileNameOverride.Trim():CurrentPlayer.CommanderId.Length>0?CurrentPlayer.Commander:localProfile.Name;
private void LoadProfileAvatar()
{
var path=File.Exists(ProfileAvatarPath)?ProfileAvatarPath:localProfile.Avatar;
ProfileAvatar=new BitmapImage(new Uri(Path.GetFullPath(path)));
}
[RelayCommand] private async Task SaveProfileAsync()
{
try{await runtime.SaveSettingsAsync(runtime.Settings with{ProfileDisplayName=ProfileNameOverride.Trim(),ProfileAvatarPath=ProfileAvatarPath});RefreshProfileName();LoadProfileAvatar();ProfileStatus="个人资料已保存。";}catch(Exception e){ProfileStatus=e.Message;}
}
[RelayCommand] private async Task ChooseProfileAvatarAsync()
{
var picker=new Windows.Storage.Pickers.FileOpenPicker();foreach(var type in new[]{".png",".jpg",".jpeg",".bmp"})picker.FileTypeFilter.Add(type);InitializePicker(picker);
if(await picker.PickSingleFileAsync() is {} file){ProfileAvatarPath=file.Path;LoadProfileAvatar();}
}
[RelayCommand] private async Task ResetProfileAsync(){ProfileNameOverride="";ProfileAvatarPath="";await SaveProfileAsync();}
}
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using XFEEDToolBox.Services;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Galaxy;
using XFEEDToolBox.Core.Presentation;
namespace XFEEDToolBox.ViewModels;
public partial class ToolboxViewModel
{
private readonly LocalUserProfile localProfile=LocalUserProfile.Read();
[ObservableProperty] public partial string ProfileDisplayName { get; set; } = "指挥官";
[ObservableProperty] public partial string ProfileNameOverride { get; set; } = "";
[ObservableProperty] public partial string ProfileAvatarPath { get; set; } = "";
[ObservableProperty] public partial ImageSource? ProfileAvatar { get; set; }
[ObservableProperty] public partial string ProfileStatus { get; set; } = "头像读取本机缓存,可在这里自定义。";
[ObservableProperty] public partial string ProfileCommanderId{get;set;}="未读取";
[ObservableProperty] public partial string ProfileCommanderName{get;set;}="等待指挥官档案";
[ObservableProperty] public partial string ProfileArxText{get;set;}="未读取";
[ObservableProperty] public partial string ProfileArxNote{get;set;}="等待游戏钱包数据";
[ObservableProperty] public partial string ProfileExplorationSummary{get;set;}="等待探索记录";
[ObservableProperty] public partial string ProfileVisitedCount{get;set;}="—";
[ObservableProperty] public partial string ProfileScannedCount{get;set;}="—";
[ObservableProperty] public partial string ProfileStatisticsTime{get;set;}="等待游戏统计";
[ObservableProperty] public partial IReadOnlyList<CommanderMetric> ProfileStatistics{get;set;}=[];
[ObservableProperty] public partial IReadOnlyList<CommanderMetric> ProfileRanks{get;set;}=[];
[ObservableProperty] public partial IReadOnlyList<GalacticSystem> ProfileExploredSystems{get;set;}=[];
[ObservableProperty] public partial IReadOnlyList<VisitedSystem> ProfileRecentVisits{get;set;}=[];
[ObservableProperty] public partial Coordinates ProfileMapCentre{get;set;}=new(0,0,0);
private IReadOnlyList<VisitedSystem>? profileMapSource;
private readonly Core.Native.ReadOnlyWalletReader walletReader=new();
private Microsoft.UI.Dispatching.DispatcherQueueTimer? walletTimer;
private bool readingWallet;
private Core.Native.GameWalletSnapshot? walletSnapshot;
private string walletOwner="";
public Core.Native.GameWalletSnapshot? WalletSnapshot=>walletSnapshot;
public async Task RefreshWalletAsync()
{
if(Environment.GetCommandLineArgs().Contains("--smoke-interface"))return;
if(readingWallet||lifetime.IsCancellationRequested)return;
readingWallet=true;
try
{
var snapshot=await Task.Run(walletReader.Read,lifetime.Token);
var player=CurrentPlayer;
if(player.CommanderId.Length==0||player.LoadGameAt is not {} loaded||loaded.UtcTicks<snapshot.StartedUtcTicks-TimeSpan.FromSeconds(5).Ticks)throw new InvalidOperationException("等待当前游戏的指挥官档案");
walletSnapshot=snapshot;walletOwner=player.CommanderId;ProfileArxText=snapshot.Arx.ToString("N0");ProfileArxNote=$"游戏钱包 · 本机读取 {snapshot.ReadAt.ToLocalTime():HH:mm:ss}";
}
catch(Exception error)when(error is not OperationCanceledException){walletSnapshot=null;ProfileArxText="未读取";ProfileArxNote=error.Message;}
finally{readingWallet=false;}
}
private void RefreshProfileData(PlayerState player)
{
ProfileCommanderId=player.CommanderId.Length>0?player.CommanderId:"未读取";
ProfileCommanderName=player.Commander.Length>0?"CMDR "+player.Commander:"等待指挥官档案";
var data=player.Profile;
if(walletOwner!=player.CommanderId)walletSnapshot=null;
if(walletSnapshot is null){ProfileArxText=data.Arx?.ToString("N0")??"未读取";ProfileArxNote=data.ArxAt is {} at?$"钱包更新 {at.ToLocalTime():MM-dd HH:mm:ss}":"等待游戏钱包数据";}
ProfileStatistics=StableSequence(ProfileStatistics,data.Statistics);ProfileRanks=StableSequence(ProfileRanks,data.Ranks);
ProfileStatisticsTime=data.StatisticsAt is {} stats?$"游戏统计 · {stats.ToLocalTime():MM-dd HH:mm:ss}":"等待游戏统计快照";
ProfileVisitedCount=data.VisitedSystems.Count.ToString("N0");ProfileScannedCount=data.ScannedBodies.ToString("N0");
ProfileExplorationSummary=$"本机已记录 {data.VisitedSystems.Count:N0} 个访问星系 · {data.ScannedBodies:N0} 个扫描天体 · 首次发现 {data.FirstDiscoveredBodies:N0}\n本机 Journal 覆盖范围内的航迹;累计统计以游戏统计快照为准。";
if(!ReferenceEquals(profileMapSource,data.VisitedSystems))
{
profileMapSource=data.VisitedSystems;
ProfileExploredSystems=data.VisitedSystems.Select(v=>new GalacticSystem(v.Name,v.Position,v.SystemAddress,v.StarClass,"指挥官访问记录")).ToArray();
ProfileRecentVisits=data.VisitedSystems.Take(100).ToArray();
}
if(player.Position is {} position)ProfileMapCentre=position;
}
private void InitializeProfile()
{
ProfileNameOverride=runtime.Settings.ProfileDisplayName;ProfileAvatarPath=runtime.Settings.ProfileAvatarPath;
RefreshProfileName();LoadProfileAvatar();
walletTimer=dispatcher.CreateTimer();walletTimer.Interval=TimeSpan.FromSeconds(5);walletTimer.Tick+=async(_,_)=>{if(initialized)await RefreshWalletAsync();};walletTimer.Start();
}
private void RefreshProfileName()=>ProfileDisplayName=ProfileNameOverride.Trim().Length>0?ProfileNameOverride.Trim():CurrentPlayer.CommanderId.Length>0?CurrentPlayer.Commander:localProfile.Name;
private void LoadProfileAvatar()
{
var path=File.Exists(ProfileAvatarPath)?ProfileAvatarPath:localProfile.Avatar;
ProfileAvatar=new BitmapImage(new Uri(Path.GetFullPath(path)));
}
[RelayCommand] private async Task SaveProfileAsync()
{
try{await runtime.SaveSettingsAsync(runtime.Settings with{ProfileDisplayName=ProfileNameOverride.Trim(),ProfileAvatarPath=ProfileAvatarPath});RefreshProfileName();LoadProfileAvatar();ProfileStatus="个人资料已保存。";}catch(Exception e){ProfileStatus=e.Message;}
}
[RelayCommand] private async Task ChooseProfileAvatarAsync()
{
var picker=new Windows.Storage.Pickers.FileOpenPicker();foreach(var type in new[]{".png",".jpg",".jpeg",".bmp"})picker.FileTypeFilter.Add(type);InitializePicker(picker);
if(await picker.PickSingleFileAsync() is {} file){ProfileAvatarPath=file.Path;LoadProfileAvatar();}
}
[RelayCommand] private async Task ResetProfileAsync(){ProfileNameOverride="";ProfileAvatarPath="";await SaveProfileAsync();}
}