XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
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();}
}