New dev build

This commit is contained in:
2025-09-06 11:14:02 -05:00
parent 700cb81f24
commit 7c4f85ec21
28 changed files with 952 additions and 17 deletions

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Threading.Tasks;
using System.Web;
using Avalonia.Markup.Xaml.Templates;
using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using CrossLangDevStudio.Messages;
using CrossLangDevStudio.Views;
using Newtonsoft.Json;
namespace CrossLangDevStudio.ViewModels;
public partial class InstallPackageDialogViewModel : ViewModelBase
{
public InstallPackageMessage Message { get; }
[ObservableProperty]
private int _versionIndex = 0;
public ObservableCollection<VersionObject> Versions { get; } = new ObservableCollection<VersionObject>();
public InstallPackageDialogViewModel(InstallPackageMessage msg)
{
Message = msg;
Task.Run(async () =>
{
var res = await Message.Client.GetStringAsync($"{msg.Server.TrimEnd('/')}/api/v1/versions?name={HttpUtility.UrlEncode(msg.Name)}");
if (!string.IsNullOrWhiteSpace(res))
{
var res2 = JsonConvert.DeserializeObject<VersionsMessage>(res);
if (res2 is not null && res2.Success)
{
foreach (var res3 in res2.Versions)
{
Versions.Add(res3.ToObject());
}
VersionIndex = 0;
}
}
});
}
[RelayCommand]
private void Install()
{
if(VersionIndex < Versions.Count)
WeakReferenceMessenger.Default.Send(new InstallPackageResponseMessage(Versions[VersionIndex].Version));
}
[RelayCommand]
private void Cancel()
{
WeakReferenceMessenger.Default.Send(new InstallPackageResponseMessage(null));
}
public partial class VersionObject(CrossLangVersion version, DateTime date) : ObservableObject
{
public CrossLangVersion Version => version;
[ObservableProperty]
private string _text = $"{version} at {date.ToShortDateString()}";
}
public class VersionsMessage
{
[JsonProperty("success")]
public bool Success { get; set; }
[JsonProperty("versions")]
public List<VersionMessage> Versions { get; set; } = new();
public class VersionMessage
{
[JsonProperty("version")]
public CrossLangVersion Version { get; set; }
[JsonProperty("uploadTime")]
public long UploadTime { get; set; } = 0;
public VersionObject ToObject()
{
return new VersionObject(Version, DateTimeOffset.FromUnixTimeSeconds(UploadTime).LocalDateTime);
}
}
}
}

View File

@@ -122,7 +122,12 @@ public partial class MainWindowViewModel : ViewModelBase
OpenProjectConfig();
}),
new ProjectFileNode("Packages")
new ProjectFileNode("Packages", ()=>{
OpenProjectPackages();
}),
new ProjectFileNode("Project Dependencies",()=>{
})
])
};
@@ -151,6 +156,33 @@ public partial class MainWindowViewModel : ViewModelBase
ProjectFiles.Add(new ProjectFileNode(Path.GetFileName(obj), entries));
}
private void OpenProjectPackages()
{
if (Directory.Exists(CurrentProject))
{
var config = Path.Combine(CurrentProject, "cross.json");
if (File.Exists(config))
{
foreach (var item in TabItems)
{
if (item.Body is PackageManagerViewModel vm)
{
if (vm.Packages is ProjectPackageManager)
{
SelectedTab = item;
return;
}
}
}
AddTab(new TabItemViewModel()
{
Header = "Project Packages",
Body = new PackageManagerViewModel(this, new ProjectPackageManager(config))
});
}
}
}
private void OpenProjectConfig()
{
@@ -161,6 +193,7 @@ public partial class MainWindowViewModel : ViewModelBase
{
if (item.Body is ProjectConfigurationViewModel model && model.FilePath == config)
{
SelectedTab = item;
return;
}
}

View File

@@ -39,7 +39,7 @@ public partial class NewProjectDialogViewModel : ViewModelBase
int i;
for (i = 1; i < int.MaxValue; i++)
{
string name2 = $"{name}{i}";
string name2 = $"{newName}{i}";
if (!Directory.Exists(Path.Combine(ParentDirectory, name2)))
{
Name = name2;

View File

@@ -0,0 +1,203 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Threading.Tasks;
using System.Web;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Platform.Storage;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using CrossLangDevStudio.Messages;
using CrossLangDevStudio.Models;
using CrossLangDevStudio.Views;
using Newtonsoft.Json;
namespace CrossLangDevStudio.ViewModels;
public partial class PackageManagerViewModel : ViewModelBase
{
public IPackageManager Packages { get; }
public ObservableCollection<Package> PackageList { get; } = new ObservableCollection<Package>();
public ObservableCollection<string> Servers { get; } = new ObservableCollection<string>();
[ObservableProperty]
private int _serverIndex = 0;
[ObservableProperty]
private string _search = "";
[ObservableProperty]
private int _page = 1;
public MainWindowViewModel Main { get; }
public PackageManagerViewModel(MainWindowViewModel mvm, IPackageManager pm)
{
Main = mvm;
Packages = pm;
foreach(var svr in CrossLangShell.GetServers())
this.Servers.Add(svr);
}
[RelayCommand]
private async Task SearchPackagesAsync()
{
var svr = Servers[ServerIndex].TrimEnd('/');
var body = await Main.Client.GetStringAsync($"{svr}/api/v1/search?q={HttpUtility.UrlEncode(Search)}&filter={HttpUtility.UrlEncode(Packages.Filter)}&offset={Page-1}&limit=20");
var res = JsonConvert.DeserializeObject<SearchResult>(body);
PackageList.Clear();
if (res is not null)
{
foreach (var item in res.Packages)
{
Package pkg = new Package();
var date = DateTimeOffset.FromUnixTimeSeconds(item.UploadTime);
var date2 = date.ToLocalTime().DateTime;
pkg.Info = $"Version: {item.Version}\tAccount: {item.AccountName}\tUpdated: {date2.ToShortDateString()}\tLicense: {item.License}\tType: {item.Type}";
pkg.Version = item.Version;
pkg.Name = item.Name;
pkg.Description = item.Description.Summarize();
pkg.IsInstalled = Packages.IsPackageInstalled(item.Name);
pkg.Install = async() =>
{
var resp = await WeakReferenceMessenger.Default.Send(new InstallPackageMessage(Main.Client, item.Name, svr));
if (resp.HasValue)
{
await Packages.InstallPackageAsync(item.Name, resp.Value);
pkg.IsInstalled = true;
}
};
pkg.Uninstall = () =>
{
Packages.UninstallPackage(item.Name);
pkg.IsInstalled = false;
};
byte[] data = await Main.Client.GetByteArrayAsync($"{svr}/api/v1/package_icon.png?name={HttpUtility.UrlEncode(item.Name)}&version={item.Version.ToString()}");
using var ms = new MemoryStream(data, false);
pkg.Icon = Bitmap.DecodeToHeight(ms, 64);
PackageList.Add(pkg);
}
}
}
public class SearchPackage
{
[JsonProperty("packageName")]
public string Name { get; set; } = "";
[JsonProperty("version")]
public CrossLangVersion Version { get; set; }
[JsonProperty("uploadTime")]
public long UploadTime { get; set; }
[JsonProperty("license")]
public string License { get; set; } = "";
[JsonProperty("type")]
public string Type { get; set; } = "";
[JsonProperty("accountName")]
public string AccountName { get; set; } = "";
[JsonProperty("description")]
public string Description { get; set; } = "";
}
public partial class Package : ObservableObject
{
[ObservableProperty]
private string _name = "";
public CrossLangVersion Version { get; set; }
public Func<Task>? Install { get; set; }
public Func<Task>? GetInfo { get; set; }
[ObservableProperty]
private string _info = "";
[ObservableProperty]
private string _description = "";
[ObservableProperty]
private IImage? _icon = null;
[ObservableProperty]
private string _mainButtonText = "";
[ObservableProperty]
private string _subButton1Text = "";
private bool _isInstalled = false;
public bool IsInstalled
{
get => _isInstalled;
set
{
SetProperty(ref _isInstalled, value, nameof(IsInstalled));
MainButtonText = value ? "Uninstall" : "Install";
SubButton1Text = value ? "Change Version" : "Info";
}
}
public Action? Uninstall { get; set; }
[RelayCommand]
private async Task MainButtonAsync()
{
/*var i = Install;
if (i is not null) await i();*/
if (_isInstalled)
{
Uninstall?.Invoke();
}
else
{
var i = Install;
if (i is not null) await i();
}
}
[RelayCommand]
private async Task SubButton1Async()
{
if (_isInstalled)
{
var i = Install;
if (i is not null) await i();
}
else
{
var i = GetInfo;
if (i is not null) await i();
}
}
[RelayCommand]
private async Task SubButton2Async()
{
var i = GetInfo;
if (i is not null) await i();
}
}
public class SearchResult
{
[JsonProperty("packages")]
public List<SearchPackage> Packages { get; set; } = new List<SearchPackage>();
}
}

View File

@@ -26,7 +26,6 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
<ComboBoxItem>Tool</ComboBoxItem>
<ComboBoxItem>Archive</ComboBoxItem>
*/
static readonly string[] types = ["console","lib","app","template","compile_tool","tool","archive"];
TabItemViewModel tab;
public string FilePath { get; }
bool _modified = false;
@@ -186,7 +185,7 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
_license = config?.Info?.License ?? "";
_templatename = config?.Info?.TemplateName ?? "";
_templatenamepretty = config?.Info?.TemplateNamePretty ?? "";
_type = Array.IndexOf(types, config?.Info?.Type ?? "console");
_type = Array.IndexOf(CrossLangShell.ProjectTypes, config?.Info?.Type ?? "console");
_type = _type == -1 ? 0 : _type;
_description = config?.Info?.Description ?? "";
@@ -210,7 +209,7 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
config.Info.Repoository = string.IsNullOrWhiteSpace(Repository) ? null : Repository;
config.Info.TemplateName = string.IsNullOrWhiteSpace(TemplateName) ? null : TemplateName;
config.Info.TemplateNamePretty = string.IsNullOrWhiteSpace(TemplateNamePretty) ? null : TemplateNamePretty;
config.Info.Type = types[Type];
config.Info.Type = CrossLangShell.ProjectTypes[Type];
File.WriteAllText(FilePath, JsonConvert.SerializeObject(config, Formatting.Indented, new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore