mirror of
https://onedev.site.tesses.net/crosslang/crosslangdevstudio
synced 2026-02-08 09:15:45 +00:00
Get way further
This commit is contained in:
92
ViewModels/AddProjectReferenceViewModel.cs
Normal file
92
ViewModels/AddProjectReferenceViewModel.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CrossLangDevStudio.Messages;
|
||||
using CrossLangDevStudio.Views;
|
||||
using MsBox.Avalonia;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
|
||||
public partial class AddProjectReferenceViewModel : ViewModelBase
|
||||
{
|
||||
public AddProjectReferenceViewModel(string projectDir)
|
||||
{
|
||||
ProjectDirectory = projectDir;
|
||||
var data = File.ReadAllText(Path.Combine(projectDir, "cross.json"));
|
||||
var jsonData = JsonConvert.DeserializeObject<CrossLangConfig>(data) ?? new CrossLangConfig();
|
||||
foreach (var item in jsonData.ProjectDependencies)
|
||||
References.Add(new ProjectReferenceEntry(this, item));
|
||||
}
|
||||
public string ProjectDirectory { get; init; }
|
||||
public ObservableCollection<ProjectReferenceEntry> References { get; } = new ObservableCollection<ProjectReferenceEntry>();
|
||||
|
||||
public void Remove(ProjectReferenceEntry projectReferenceEntry)
|
||||
{
|
||||
References.Remove(projectReferenceEntry);
|
||||
var data = File.ReadAllText(Path.Combine(ProjectDirectory, "cross.json"));
|
||||
var jsonData = JsonConvert.DeserializeObject<CrossLangConfig>(data) ?? new CrossLangConfig();
|
||||
jsonData.ProjectDependencies.Remove(projectReferenceEntry.Path);
|
||||
File.WriteAllText(Path.Combine(ProjectDirectory, "cross.json"), JsonConvert.SerializeObject(jsonData, Formatting.Indented, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore }));
|
||||
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task AddProjectAsync()
|
||||
{
|
||||
var window = await WeakReferenceMessenger.Default.Send<GetWindowMessage>();
|
||||
var dir = await window.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions() { Title = "Add Project Dependency" });
|
||||
if (dir.Count != 0)
|
||||
{
|
||||
string? path = dir[0].TryGetLocalPath();
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
var jsonFile = Path.Combine(path, "cross.json");
|
||||
if (!File.Exists(jsonFile))
|
||||
{
|
||||
await MessageBoxManager.GetMessageBoxStandard("Error", $"Could not find cross.json in folder {path}", MsBox.Avalonia.Enums.ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error).ShowAsync();
|
||||
return;
|
||||
}
|
||||
string projectPath = Path.GetRelativePath(this.ProjectDirectory, path);
|
||||
var abs = Path.GetFullPath(projectPath, ProjectDirectory);
|
||||
|
||||
foreach (var item in References)
|
||||
{
|
||||
if (Path.GetFullPath(item.Path, ProjectDirectory) == abs)
|
||||
{
|
||||
await MessageBoxManager.GetMessageBoxStandard("Error", $"Project {path} already exists in your project.", MsBox.Avalonia.Enums.ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error).ShowAsync();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
var data = File.ReadAllText(Path.Combine(ProjectDirectory, "cross.json"));
|
||||
var jsonData = JsonConvert.DeserializeObject<CrossLangConfig>(data) ?? new CrossLangConfig();
|
||||
jsonData.ProjectDependencies.Add(projectPath);
|
||||
File.WriteAllText(Path.Combine(ProjectDirectory, "cross.json"), JsonConvert.SerializeObject(jsonData, Formatting.Indented, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore }));
|
||||
References.Add(new ProjectReferenceEntry(this, projectPath));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class ProjectReferenceEntry(AddProjectReferenceViewModel parent,string path) : ObservableObject
|
||||
{
|
||||
public string Path => path;
|
||||
|
||||
[RelayCommand]
|
||||
private void Remove()
|
||||
{
|
||||
parent.Remove(this);
|
||||
}
|
||||
}
|
||||
103
ViewModels/CRVMViewerViewModel.cs
Normal file
103
ViewModels/CRVMViewerViewModel.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CrossLangDevStudio.Messages;
|
||||
using CrossLangDevStudio.Views;
|
||||
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
public class CRVMViewerViewModel : ViewModelBase
|
||||
{
|
||||
public string FilePath { get; set; }
|
||||
public CRVMViewerViewModel(string path)
|
||||
{
|
||||
FilePath = path;
|
||||
var clf = new CrossLangFile();
|
||||
using (var strm = File.OpenRead(path))
|
||||
{
|
||||
|
||||
clf.Load(strm);
|
||||
|
||||
}
|
||||
|
||||
|
||||
foreach (var fn in clf.Functions)
|
||||
{
|
||||
string docs = $"/^{fn.NameParts[0]}^/";
|
||||
string name = string.Join(".", fn.NameParts.Skip(1));
|
||||
string args = string.Join(", ", clf.Chunks[(int)fn.ChunkId]);
|
||||
Functions.Add(new Function(docs, name, args));
|
||||
}
|
||||
foreach (var cls in clf.Classes)
|
||||
{
|
||||
string docs = $"/^{cls.Documentation}^/";
|
||||
ObservableCollection<Class.ClassEntry> entries = new ObservableCollection<Class.ClassEntry>();
|
||||
|
||||
foreach (var item in cls.Entries)
|
||||
{
|
||||
string modifiers = $"\t{item.Modifier.ToString().ToLower()} ";
|
||||
if (item.IsFunction && item.IsAbstract)
|
||||
modifiers += "abstract ";
|
||||
|
||||
Class.ClassEntry ce = new Class.ClassEntry($"\t/^{item.Documentation}^/", item.Name, modifiers, item.IsFunction, item.IsFunction ? string.Join(", ", item.Arguments) : "");
|
||||
entries.Add(ce);
|
||||
}
|
||||
|
||||
Classes.Add(new Class(docs, cls.Name, cls.Inherit, entries));
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<Function> Functions { get; set; } = new ObservableCollection<Function>();
|
||||
|
||||
public ObservableCollection<Class> Classes { get; set; } = new ObservableCollection<Class>();
|
||||
|
||||
public class Function(string docs, string name, string args) : ObservableObject
|
||||
{
|
||||
public string Name => name;
|
||||
|
||||
public string Documentation => docs;
|
||||
|
||||
public string Args => args;
|
||||
}
|
||||
|
||||
public class Class(string docs, string name, string inherits, ObservableCollection<Class.ClassEntry> entries) : ObservableObject
|
||||
{
|
||||
public string Documentation => docs;
|
||||
|
||||
public string Name => name;
|
||||
|
||||
public string Inherits => inherits == "ClassObject" ? "" : inherits;
|
||||
|
||||
public string InheritsColon => inherits == "ClassObject" ? "" : " : ";
|
||||
|
||||
public ObservableCollection<ClassEntry> Entries => entries;
|
||||
|
||||
public class ClassEntry(string docs,string name, string modifiers, bool isFunction, string args)
|
||||
{
|
||||
public string Documentation => docs;
|
||||
|
||||
public string Name => name;
|
||||
public string Modifiers => modifiers;
|
||||
|
||||
public IBrush NameColor => new SolidColorBrush(isFunction ? 0xFFDCDCAA : 0xFF9CDCFE);
|
||||
|
||||
public IBrush LeftParenColor => new SolidColorBrush(isFunction ? 0xFFC586C0 : 0xFFCCCCCC);
|
||||
|
||||
public string LeftParen => isFunction ? "(" : ";";
|
||||
|
||||
public string RightParen => isFunction ? ")" : "";
|
||||
|
||||
|
||||
public string Args => args;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,22 @@ using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
using AvaloniaEdit;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CrossLangDevStudio.Messages;
|
||||
using CrossLangDevStudio.Views;
|
||||
|
||||
using AvaloniaEdit.CodeCompletion;
|
||||
using AvaloniaEdit.Document;
|
||||
using AvaloniaEdit.Editing;
|
||||
using AvaloniaEdit.Folding;
|
||||
using AvaloniaEdit.Rendering;
|
||||
using TextMateSharp.Grammars;
|
||||
using AvaloniaEdit.TextMate;
|
||||
using Avalonia.Input;
|
||||
using System.Collections.Generic;
|
||||
using Avalonia.Media;
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
public partial class FileEditorViewModel : ViewModelBase, ISavable
|
||||
@@ -19,7 +28,7 @@ public partial class FileEditorViewModel : ViewModelBase, ISavable
|
||||
TabItemViewModel tab;
|
||||
public string FilePath { get; }
|
||||
bool _modified = false;
|
||||
private bool Modified
|
||||
public bool Modified
|
||||
{
|
||||
get => _modified;
|
||||
set
|
||||
@@ -36,30 +45,72 @@ public partial class FileEditorViewModel : ViewModelBase, ISavable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string _text = "";
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => _text;
|
||||
set
|
||||
{
|
||||
|
||||
Modified = true;
|
||||
this.SetProperty(ref _text, value, nameof(Text));
|
||||
}
|
||||
}
|
||||
|
||||
public FileEditorViewModel(string path,TabItemViewModel tab)
|
||||
TextEditor textEdit = new TextEditor();
|
||||
|
||||
public TextEditor TextEditor => textEdit;
|
||||
|
||||
|
||||
|
||||
public FileEditorViewModel(string path, TabItemViewModel tab)
|
||||
{
|
||||
this.tab = tab;
|
||||
FilePath = path;
|
||||
_text = File.ReadAllText(path);
|
||||
textEdit.ShowLineNumbers = true;
|
||||
textEdit.FontSize = 24;
|
||||
string ext = Path.GetExtension(FilePath);
|
||||
if (ext == ".tcross")
|
||||
{
|
||||
ext = ".go";
|
||||
}
|
||||
{
|
||||
|
||||
var _registryOptions = new RegistryOptions(ThemeName.Dark);
|
||||
|
||||
var _textMateInstallation = textEdit.InstallTextMate(_registryOptions);
|
||||
|
||||
//definition.
|
||||
|
||||
|
||||
|
||||
//Here we are getting the language by the extension and right after that we are initializing grammar with this language.
|
||||
//And that's all 😀, you are ready to use AvaloniaEdit with syntax highlighting!
|
||||
try
|
||||
{
|
||||
//AssetLoader.Open(new Uri("avares://CrossLangDevStudio/Assets/crosslang.png")
|
||||
|
||||
_textMateInstallation.SetGrammar(_registryOptions.GetScopeByLanguageId(_registryOptions.GetLanguageByExtension(ext).Id));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
textEdit.Text = File.ReadAllText(path);
|
||||
textEdit.TextChanged += (sender, e) =>
|
||||
{
|
||||
Modified = true;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public void Save()
|
||||
{
|
||||
File.WriteAllText(FilePath, Text);
|
||||
|
||||
File.WriteAllText(FilePath, textEdit.Text);
|
||||
Modified = false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveRecovery(string path)
|
||||
{
|
||||
|
||||
File.WriteAllText(path, textEdit.Text);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
interface ISavable
|
||||
{
|
||||
string FilePath { get; }
|
||||
bool Modified { get; set; }
|
||||
void Save();
|
||||
|
||||
void SaveRecovery(string path);
|
||||
}
|
||||
@@ -2,15 +2,21 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CrossLangDevStudio.Messages;
|
||||
using CrossLangDevStudio.Models;
|
||||
using CrossLangDevStudio.Views;
|
||||
using MsBox.Avalonia;
|
||||
using MsBox.Avalonia.Enums;
|
||||
using Newtonsoft.Json;
|
||||
using Tabalonia.Events;
|
||||
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
@@ -26,6 +32,7 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
public ObservableCollection<ProjectFileNode> ProjectFiles { get; } = new ObservableCollection<ProjectFileNode>();
|
||||
|
||||
public EventHandler<Tabalonia.Events.CloseLastTabEventArgs>? Closed { get; } = null;
|
||||
public EventHandler<Tabalonia.Events.TabClosingEventArgs>? ClosingTab { get; }
|
||||
|
||||
public TabItemViewModel WelcomePage
|
||||
{
|
||||
@@ -49,16 +56,120 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
value?.Click?.Invoke();
|
||||
}
|
||||
}
|
||||
private Avalonia.Threading.DispatcherTimer timer=new ();
|
||||
|
||||
[RelayCommand]
|
||||
private void Welcome()
|
||||
{
|
||||
foreach (var item in TabItems)
|
||||
{
|
||||
if (item.Body is WelcomeViewModel)
|
||||
{
|
||||
SelectedTab = item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
AddTab(WelcomePage);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task WebsiteAsync()
|
||||
{
|
||||
var win = await WeakReferenceMessenger.Default.Send<GetWindowMessage>(new GetWindowMessage());
|
||||
if (win is not null)
|
||||
{
|
||||
await win.Launcher.LaunchUriAsync(new Uri("https://crosslang.tesseslanguage.com/"));
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task VideoDocumentationAsync()
|
||||
{
|
||||
var win = await WeakReferenceMessenger.Default.Send<GetWindowMessage>(new GetWindowMessage());
|
||||
if (win is not null)
|
||||
{
|
||||
await win.Launcher.LaunchUriAsync(new Uri("https://peertube.site.tesses.net/c/crosslang"));
|
||||
}
|
||||
}
|
||||
[RelayCommand]
|
||||
private async Task DocumentationAsync()
|
||||
{
|
||||
var win = await WeakReferenceMessenger.Default.Send<GetWindowMessage>(new GetWindowMessage());
|
||||
if (win is not null)
|
||||
{
|
||||
await win.Launcher.LaunchUriAsync(new Uri("https://crosslang.tesseslanguage.com/language-features/index.html"));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CloseTabAsync(TabClosingEventArgs e, ISavable savable)
|
||||
{
|
||||
var box = MessageBoxManager
|
||||
.GetMessageBoxStandard("Save?", $"Do you want to save {Path.GetFileName(savable.FilePath)}.?",
|
||||
ButtonEnum.YesNoCancel, Icon.Question);
|
||||
var msg = await WeakReferenceMessenger.Default.Send<GetWindowMessage>();
|
||||
if (msg is not null)
|
||||
{
|
||||
switch (await box.ShowWindowDialogAsync(msg))
|
||||
{
|
||||
case ButtonResult.Yes:
|
||||
savable.Save();
|
||||
break;
|
||||
case ButtonResult.Cancel:
|
||||
e.Cancel = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasUnsaved
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var item in TabItems)
|
||||
{
|
||||
if (item.Body is ISavable s && s.Modified) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public MainWindowViewModel(string[] args)
|
||||
{
|
||||
this.ClosingTab = (sender, e) =>
|
||||
{
|
||||
|
||||
if (e.Item is TabItemViewModel vm)
|
||||
{
|
||||
if (vm.Body is ISavable savable)
|
||||
{
|
||||
if (savable.Modified)
|
||||
{
|
||||
//thanks https://github.com/AvaloniaUI/Avalonia/issues/4810#issuecomment-704372304
|
||||
using (var source = new CancellationTokenSource())
|
||||
{
|
||||
CloseTabAsync(e, savable).ContinueWith(e => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext());
|
||||
Dispatcher.UIThread.MainLoop(source.Token);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
timer.Interval = TimeSpan.FromMinutes(1);
|
||||
timer.Tick += (sender, e) =>
|
||||
{
|
||||
SaveRecovery();
|
||||
};
|
||||
|
||||
if (args.Length == 1)
|
||||
{
|
||||
LoadProject(args[0]);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(CurrentProject))
|
||||
this.TabItems.Add(WelcomePage);
|
||||
this.TabItems.Add(WelcomePage);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +185,7 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
var newTabItem = new NewTabViewModel(this, tab);
|
||||
tab.Body = newTabItem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return tab;
|
||||
@@ -82,12 +193,19 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
|
||||
internal void LoadProject(string obj)
|
||||
{
|
||||
timer.Stop(); //we don't want autorecovery timer ticking when we change projects
|
||||
if (!File.Exists(Path.Combine(obj, "cross.json")))
|
||||
{
|
||||
return;
|
||||
}
|
||||
CrossLangShell.EnsureRecent(obj);
|
||||
CurrentProject = obj.TrimEnd(Path.DirectorySeparatorChar);
|
||||
//we don't care that it isn't awaited due to only Refreshing here (you can referesh in GUI)
|
||||
//and the timer starting after async call inside the async function
|
||||
//so I think I know what I am doing
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
InitRecoveryAsync();
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
Refresh(CurrentProject);
|
||||
}
|
||||
[RelayCommand]
|
||||
@@ -102,7 +220,7 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
|
||||
private void Refresh(string obj)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < TabItems.Count; i++)
|
||||
@@ -122,11 +240,11 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
|
||||
OpenProjectConfig();
|
||||
}),
|
||||
new ProjectFileNode("Packages", ()=>{
|
||||
new ProjectFileNode("Project Packages", ()=>{
|
||||
OpenProjectPackages();
|
||||
}),
|
||||
new ProjectFileNode("Project Dependencies",()=>{
|
||||
|
||||
new ProjectFileNode("Project Dependencies (folders)",()=>{
|
||||
OpenProjectDependencies();
|
||||
})
|
||||
])
|
||||
|
||||
@@ -155,7 +273,227 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
ProjectFiles.Clear();
|
||||
ProjectFiles.Add(new ProjectFileNode(Path.GetFileName(obj), entries));
|
||||
}
|
||||
private int proj_id = -1;
|
||||
private async Task InitRecoveryAsync()
|
||||
{
|
||||
int i = 0;
|
||||
var dir = Path.Combine(CrossLangShell.CrossLangConfigDirectory, "DevStudio", "Recovery");
|
||||
foreach (var item in Directory.EnumerateDirectories(dir))
|
||||
{
|
||||
if (int.TryParse(Path.GetFileName(item), out int id))
|
||||
{
|
||||
if (id >= i) i = id + 1;
|
||||
|
||||
var file = $"{item}.json";
|
||||
if (File.Exists(file))
|
||||
{
|
||||
var cfg = JsonConvert.DeserializeObject<RecoveryConfig>(File.ReadAllText(file));
|
||||
if (cfg is not null)
|
||||
{
|
||||
if (cfg.ProjectDirectory == CurrentProject)
|
||||
{
|
||||
proj_id = id;
|
||||
|
||||
if (cfg.HasRecovery)
|
||||
{
|
||||
var box = MessageBoxManager
|
||||
.GetMessageBoxStandard("Autorecovery", $"Found a autorecovery from {cfg.Date} do you want to load it?",
|
||||
ButtonEnum.YesNo, Icon.Question);
|
||||
var msg = await WeakReferenceMessenger.Default.Send<GetWindowMessage>();
|
||||
if (msg is not null && await box.ShowWindowDialogAsync(msg) == ButtonResult.Yes)
|
||||
{
|
||||
CopyDir(item, CurrentProject);
|
||||
|
||||
|
||||
}
|
||||
cfg.HasRecovery = false;
|
||||
File.WriteAllText(file, JsonConvert.SerializeObject(cfg));
|
||||
}
|
||||
|
||||
//WeakReferenceMessenger.Default.Send
|
||||
|
||||
timer.Start();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proj_id = i;
|
||||
|
||||
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
private void CopyDir(string src, string dest)
|
||||
{
|
||||
foreach (var dir in Directory.EnumerateDirectories(src))
|
||||
{
|
||||
var destDir = Path.Combine(dest, Path.GetFileName(dir));
|
||||
Directory.CreateDirectory(destDir);
|
||||
CopyDir(dir, destDir);
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(src))
|
||||
{
|
||||
var destFile = Path.Combine(dest, Path.GetFileName(file));
|
||||
|
||||
File.Copy(file, destFile, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveRecovery()
|
||||
{
|
||||
if (proj_id == -1 || !Directory.Exists(CurrentProject)) return;
|
||||
var id = proj_id;
|
||||
var dir = Path.Combine(CrossLangShell.CrossLangConfigDirectory, "DevStudio", "Recovery", $"{id}_tmp");
|
||||
var dirdest = Path.Combine(CrossLangShell.CrossLangConfigDirectory, "DevStudio", "Recovery", $"{id}");
|
||||
Directory.CreateDirectory(dir);
|
||||
bool hasAnything = false;
|
||||
|
||||
foreach (var item in TabItems)
|
||||
{
|
||||
if (item.Body is ISavable savable && savable.Modified)
|
||||
{
|
||||
if (savable.FilePath.StartsWith(CurrentProject))
|
||||
{
|
||||
var path = Path.GetRelativePath(CurrentProject, savable.FilePath);
|
||||
string? dirPath = Path.GetDirectoryName(path);
|
||||
if (dirPath is not null)
|
||||
Directory.CreateDirectory(Path.Combine(dir, dirPath));
|
||||
|
||||
savable.SaveRecovery(Path.Combine(dir, path));
|
||||
hasAnything = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Directory.Exists(dirdest))
|
||||
{
|
||||
Directory.Delete(dirdest, true);
|
||||
}
|
||||
if (hasAnything)
|
||||
{
|
||||
Directory.Move(dir, dirdest);
|
||||
File.WriteAllText($"{dirdest}.json", JsonConvert.SerializeObject(new RecoveryConfig { Date = DateTime.Now, ProjectDirectory = CurrentProject, HasRecovery=true }));
|
||||
}
|
||||
else
|
||||
{
|
||||
Directory.Delete(dir, true);
|
||||
|
||||
File.WriteAllText($"{dirdest}.json", JsonConvert.SerializeObject(new RecoveryConfig { Date = DateTime.Now, ProjectDirectory = CurrentProject, HasRecovery=false }));
|
||||
}
|
||||
Directory.CreateDirectory(dirdest);
|
||||
}
|
||||
[RelayCommand]
|
||||
private void InstallTool()
|
||||
{
|
||||
foreach (var item in TabItems)
|
||||
{
|
||||
if (item.Body is PackageManagerViewModel vm)
|
||||
{
|
||||
if (vm.Packages is ToolPackageManager)
|
||||
{
|
||||
SelectedTab = item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
AddTab(new TabItemViewModel()
|
||||
{
|
||||
Header = "Tool Packages",
|
||||
Body = new PackageManagerViewModel(this, new ToolPackageManager())
|
||||
});
|
||||
}
|
||||
[RelayCommand]
|
||||
private void InstallTemplate()
|
||||
{
|
||||
foreach (var item in TabItems)
|
||||
{
|
||||
if (item.Body is PackageManagerViewModel vm)
|
||||
{
|
||||
if (vm.Packages is TemplatePackageManager)
|
||||
{
|
||||
SelectedTab = item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
AddTab(new TabItemViewModel()
|
||||
{
|
||||
Header = "Template Packages",
|
||||
Body = new PackageManagerViewModel(this, new TemplatePackageManager())
|
||||
});
|
||||
}
|
||||
[RelayCommand]
|
||||
private void InstallConsole()
|
||||
{
|
||||
foreach (var item in TabItems)
|
||||
{
|
||||
if (item.Body is PackageManagerViewModel vm)
|
||||
{
|
||||
if (vm.Packages is ConsolePackageManager)
|
||||
{
|
||||
SelectedTab = item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
AddTab(new TabItemViewModel()
|
||||
{
|
||||
Header = "Console Packages",
|
||||
Body = new PackageManagerViewModel(this, new ConsolePackageManager())
|
||||
});
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void InstallWebApp()
|
||||
{
|
||||
foreach (var item in TabItems)
|
||||
{
|
||||
if (item.Body is PackageManagerViewModel vm)
|
||||
{
|
||||
if (vm.Packages is WebAppPackageManager)
|
||||
{
|
||||
SelectedTab = item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
AddTab(new TabItemViewModel()
|
||||
{
|
||||
Header = "Web Application Packages",
|
||||
Body = new PackageManagerViewModel(this, new WebAppPackageManager())
|
||||
});
|
||||
}
|
||||
private void OpenProjectDependencies()
|
||||
{
|
||||
if (Directory.Exists(CurrentProject))
|
||||
{
|
||||
var config = Path.Combine(CurrentProject, "cross.json");
|
||||
if (File.Exists(config))
|
||||
{
|
||||
foreach (var item in TabItems)
|
||||
{
|
||||
if (item.Body is AddProjectReferenceViewModel vm)
|
||||
{
|
||||
if (vm.ProjectDirectory == CurrentProject)
|
||||
{
|
||||
SelectedTab = item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
AddTab(new TabItemViewModel()
|
||||
{
|
||||
Header = "Project Dependencies (folders)",
|
||||
Body = new AddProjectReferenceViewModel(CurrentProject)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
private void OpenProjectPackages()
|
||||
{
|
||||
if (Directory.Exists(CurrentProject))
|
||||
@@ -185,7 +523,7 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
|
||||
private void OpenProjectConfig()
|
||||
{
|
||||
|
||||
|
||||
if (Directory.Exists(CurrentProject))
|
||||
{
|
||||
var config = Path.Combine(CurrentProject, "cross.json");
|
||||
@@ -200,12 +538,23 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
TabItemViewModel vm = new TabItemViewModel();
|
||||
vm.Header = "Project Configuration";
|
||||
var pcm = new ProjectConfigurationViewModel(config, vm);
|
||||
|
||||
|
||||
vm.Body = pcm;
|
||||
|
||||
AddTab(vm);
|
||||
}
|
||||
}
|
||||
[RelayCommand]
|
||||
private async Task ReferenceAsync()
|
||||
{
|
||||
await CrossLangShell.RunCommandAsync(Environment.CurrentDirectory, "crosslang", "docs", "--reference");
|
||||
var refFile = Path.Combine(CrossLangShell.CrossLangConfigDirectory, "Reference.crvm");
|
||||
Console.WriteLine(refFile);
|
||||
if(File.Exists(refFile))
|
||||
{
|
||||
OpenFile(refFile);
|
||||
}
|
||||
}
|
||||
|
||||
static string[] FILE_EXTS = new string[]{
|
||||
".tcross",
|
||||
@@ -232,12 +581,17 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
public void OpenFile(string path)
|
||||
{
|
||||
bool isValid = false;
|
||||
string ext = Path.GetExtension(path).ToLower();
|
||||
foreach (var item in FILE_EXTS)
|
||||
{
|
||||
if (Path.GetExtension(path).ToLower() == item)
|
||||
if (ext == item)
|
||||
isValid = true;
|
||||
}
|
||||
if (!isValid) return;
|
||||
if (!isValid)
|
||||
{
|
||||
OpenOtherFile(path, ext);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var item in TabItems)
|
||||
{
|
||||
@@ -255,10 +609,39 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
Header = Path.GetFileName(path),
|
||||
|
||||
};
|
||||
tab.Body = new FileEditorViewModel(path,tab);
|
||||
tab.Body = new FileEditorViewModel(path, tab);
|
||||
AddTab(tab);
|
||||
}
|
||||
|
||||
private void OpenOtherFile(string path, string ext)
|
||||
{
|
||||
if (ext == ".crvm")
|
||||
{
|
||||
foreach (var item in TabItems)
|
||||
{
|
||||
if (item.Body is CRVMViewerViewModel model)
|
||||
{
|
||||
if (model.FilePath == path)
|
||||
{
|
||||
SelectedTab = item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
var tab = new TabItemViewModel()
|
||||
{
|
||||
Header = Path.GetFileName(path),
|
||||
Body = new CRVMViewerViewModel(path)
|
||||
};
|
||||
|
||||
AddTab(tab);
|
||||
}catch(Exception ex) { Console.WriteLine(ex); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
private TabItemViewModel? _selectedTab = null;
|
||||
private void AddTab(TabItemViewModel item)
|
||||
@@ -337,13 +720,57 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
SelectedTab?.Save();
|
||||
}
|
||||
[RelayCommand]
|
||||
private void SaveAll()
|
||||
public void SaveAll()
|
||||
{
|
||||
foreach (var tab in TabItems)
|
||||
{
|
||||
tab.Save();
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void AddPackage()
|
||||
{
|
||||
if (Directory.Exists(CurrentProject))
|
||||
{
|
||||
var conf = Path.Combine(CurrentProject, "cross.json");
|
||||
if (File.Exists(conf))
|
||||
{
|
||||
OpenProjectPackages();
|
||||
}
|
||||
}
|
||||
}
|
||||
[RelayCommand]
|
||||
private async Task PublishAsync()
|
||||
{
|
||||
SaveAll();
|
||||
if(Directory.Exists(CurrentProject))
|
||||
await WeakReferenceMessenger.Default.Send(new PublishMessage(CurrentProject));
|
||||
}
|
||||
[RelayCommand]
|
||||
private async Task PushPackageAsync()
|
||||
{
|
||||
SaveAll();
|
||||
if (Directory.Exists(CurrentProject))
|
||||
{
|
||||
var box = MessageBoxManager
|
||||
.GetMessageBoxStandard("Push Package Confirmation", $"Are you sure you want to push the package?",
|
||||
ButtonEnum.YesNo, Icon.Question);
|
||||
var msg = await WeakReferenceMessenger.Default.Send<GetWindowMessage>();
|
||||
if (msg is not null && await box.ShowWindowDialogAsync(msg) == ButtonResult.Yes)
|
||||
|
||||
CrossLangShell.PushProjectInFolder(CurrentProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class RecoveryConfig
|
||||
{
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
public string ProjectDirectory { get; set; } = "";
|
||||
|
||||
public bool HasRecovery { get; set; }
|
||||
}
|
||||
|
||||
public partial class NewTabViewModel : ViewModelBase
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Markup.Xaml.Templates;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform.Storage;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
@@ -85,6 +87,20 @@ public partial class NewProjectDialogViewModel : ViewModelBase
|
||||
}
|
||||
}
|
||||
}
|
||||
[RelayCommand]
|
||||
public async Task BrowseAsync()
|
||||
{
|
||||
var window = await WeakReferenceMessenger.Default.Send<GetWindowMessage>();
|
||||
|
||||
|
||||
var res = await window.StorageProvider.OpenFolderPickerAsync(new Avalonia.Platform.Storage.FolderPickerOpenOptions() { Title = "Pick Project Parent Folder" });
|
||||
if (res.Count != 0)
|
||||
{
|
||||
string? path = res[0].TryGetLocalPath();
|
||||
if(!string.IsNullOrWhiteSpace(path))
|
||||
this.ParentDirectory = path;
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void OK()
|
||||
@@ -111,7 +127,7 @@ public partial class CrossLangTemplate(string name,CrossLangFile file) : Observa
|
||||
{
|
||||
|
||||
[ObservableProperty]
|
||||
private string _name = file.GetTemplatePrettyName();
|
||||
private string _name = file.GetPrettyName();
|
||||
[ObservableProperty]
|
||||
private IImage _icon = file.GetIcon(64);
|
||||
|
||||
|
||||
@@ -49,12 +49,12 @@ public partial class PackageManagerViewModel : ViewModelBase
|
||||
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 body = await Main.Client.GetStringAsync($"{svr}/api/v1/search?q={HttpUtility.UrlEncode(Search)}&type={HttpUtility.UrlEncode(Packages.Filter)}&offset={Page-1}&limit=20");
|
||||
var res = JsonConvert.DeserializeObject<SearchResult>(body);
|
||||
PackageList.Clear();
|
||||
if (res is not null)
|
||||
|
||||
@@ -29,7 +29,7 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
||||
TabItemViewModel tab;
|
||||
public string FilePath { get; }
|
||||
bool _modified = false;
|
||||
private bool Modified
|
||||
public bool Modified
|
||||
{
|
||||
get => _modified;
|
||||
set
|
||||
@@ -56,8 +56,8 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
||||
|
||||
string _license;
|
||||
|
||||
string _templatename;
|
||||
string _templatenamepretty;
|
||||
string _shortname;
|
||||
string _shortnamepretty;
|
||||
|
||||
string _description;
|
||||
|
||||
@@ -130,22 +130,22 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
||||
}
|
||||
}
|
||||
|
||||
public string TemplateName
|
||||
public string ShortName
|
||||
{
|
||||
get => _templatename;
|
||||
get => _shortname;
|
||||
set
|
||||
{
|
||||
Modified = true;
|
||||
SetProperty(ref _templatename, value, nameof(TemplateName));
|
||||
SetProperty(ref _shortname, value, nameof(ShortName));
|
||||
}
|
||||
}
|
||||
public string TemplateNamePretty
|
||||
public string ShortNamePretty
|
||||
{
|
||||
get => _templatenamepretty;
|
||||
get => _shortnamepretty;
|
||||
set
|
||||
{
|
||||
Modified = true;
|
||||
SetProperty(ref _templatenamepretty, value, nameof(TemplateNamePretty));
|
||||
SetProperty(ref _shortnamepretty, value, nameof(ShortNamePretty));
|
||||
}
|
||||
}
|
||||
public string Description
|
||||
@@ -183,8 +183,8 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
||||
_homepage = config?.Info?.HomePage ?? "";
|
||||
_maintainer = config?.Info?.Maintainer ?? "";
|
||||
_license = config?.Info?.License ?? "";
|
||||
_templatename = config?.Info?.TemplateName ?? "";
|
||||
_templatenamepretty = config?.Info?.TemplateNamePretty ?? "";
|
||||
_shortname = config?.Info?.ShortName ?? "";
|
||||
_shortnamepretty = config?.Info?.ShortNamePretty ?? "";
|
||||
_type = Array.IndexOf(CrossLangShell.ProjectTypes, config?.Info?.Type ?? "console");
|
||||
_type = _type == -1 ? 0 : _type;
|
||||
_description = config?.Info?.Description ?? "";
|
||||
@@ -193,6 +193,12 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
||||
[RelayCommand]
|
||||
|
||||
public void Save()
|
||||
{
|
||||
SaveRecovery(FilePath);
|
||||
Modified = false;
|
||||
}
|
||||
|
||||
public void SaveRecovery(string path)
|
||||
{
|
||||
var config = JsonConvert.DeserializeObject<CrossLangConfig>(File.ReadAllText(FilePath)) ?? new CrossLangConfig();
|
||||
config.Name = Name;
|
||||
@@ -207,13 +213,12 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
||||
config.Info.License = string.IsNullOrWhiteSpace(License) ? null : License;
|
||||
config.Info.Maintainer = string.IsNullOrWhiteSpace(Maintainer) ? null : Maintainer;
|
||||
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.ShortName = string.IsNullOrWhiteSpace(ShortName) ? null : ShortName;
|
||||
config.Info.ShortNamePretty = string.IsNullOrWhiteSpace(ShortNamePretty) ? null : ShortNamePretty;
|
||||
config.Info.Type = CrossLangShell.ProjectTypes[Type];
|
||||
File.WriteAllText(FilePath, JsonConvert.SerializeObject(config, Formatting.Indented, new JsonSerializerSettings()
|
||||
File.WriteAllText(path, JsonConvert.SerializeObject(config, Formatting.Indented, new JsonSerializerSettings()
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
}));
|
||||
Modified = false;
|
||||
}
|
||||
}
|
||||
279
ViewModels/PublishDialogViewModel.cs
Normal file
279
ViewModels/PublishDialogViewModel.cs
Normal file
@@ -0,0 +1,279 @@
|
||||
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;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using ICSharpCode.SharpZipLib.Tar;
|
||||
using ICSharpCode.SharpZipLib.GZip;
|
||||
using ICSharpCode.SharpZipLib.BZip2;
|
||||
using System.Text;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
public partial class PublishDialogViewModel : ViewModelBase
|
||||
{
|
||||
public string Path { get; }
|
||||
public PublishDialogViewModel(string path)
|
||||
{
|
||||
Path = path;
|
||||
foreach (var item in CrossLangShell.GetServers())
|
||||
{
|
||||
Servers.Add(item);
|
||||
}
|
||||
Targets.Add(new Target("copy", "Just Copy"));
|
||||
Targets.Add(new Target("crvm", "Merge"));
|
||||
Targets.Add(new Target("cmake", "CMake"));
|
||||
Targets.Add(new Target("header", "C++ Header"));
|
||||
this.TargetIndex = 0;
|
||||
}
|
||||
[ObservableProperty]
|
||||
private string _prefix = "Tesses.CrossLang.Runtime";
|
||||
|
||||
public ObservableCollection<string> Servers { get; } = new ObservableCollection<string>();
|
||||
[ObservableProperty]
|
||||
private int _serverIndex = 0;
|
||||
public ObservableCollection<Target> Targets { get; } = new ObservableCollection<Target>();
|
||||
[ObservableProperty]
|
||||
private int _targetIndex = 0;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _output = "";
|
||||
int _ot=0;
|
||||
public int OutputType
|
||||
{
|
||||
get => _ot;
|
||||
set {
|
||||
_ot = value;
|
||||
switch(value)
|
||||
{
|
||||
case 0:
|
||||
OutputLabel = "Directory To Publish To (Optional)";
|
||||
break;
|
||||
case 1:
|
||||
OutputLabel = "Zip Path";
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
OutputLabel = "Tar Path";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
private string _outputLabel = "Directory To Publish To (Optional)";
|
||||
|
||||
[RelayCommand]
|
||||
private async Task BrowseAsync()
|
||||
{
|
||||
var window = await WeakReferenceMessenger.Default.Send<GetWindowMessage>();
|
||||
|
||||
if (OutputType == 0)
|
||||
{
|
||||
var res = await window.StorageProvider.OpenFolderPickerAsync(new Avalonia.Platform.Storage.FolderPickerOpenOptions() { Title = "Pick publish folder" });
|
||||
if (res.Count != 0)
|
||||
{
|
||||
string? path = res[0].TryGetLocalPath();
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
this.Output = path;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string ext = "zip";
|
||||
switch(OutputType)
|
||||
{
|
||||
case 2:
|
||||
ext = "tar";
|
||||
break;
|
||||
case 3:
|
||||
ext = "tar.gz";
|
||||
break;
|
||||
case 4:
|
||||
ext = "tar.bz2";
|
||||
break;
|
||||
}
|
||||
|
||||
var res = await window.StorageProvider.SaveFilePickerAsync(new Avalonia.Platform.Storage.FilePickerSaveOptions() { Title = $"Save {ext}", DefaultExtension = $".{ext}" , FileTypeChoices = [new FilePickerFileType(ext.ToUpper()){ Patterns =[$".{ext}"]}]});
|
||||
if (res is not null)
|
||||
{
|
||||
string? path = res.TryGetLocalPath();
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
this.Output = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task LoadAsync()
|
||||
{
|
||||
Targets.Clear();
|
||||
Targets.Add(new Target("copy", "Just Copy"));
|
||||
Targets.Add(new Target("crvm", "Merge"));
|
||||
Targets.Add(new Target("cmake", "CMake"));
|
||||
Targets.Add(new Target("header", "C++ Header"));
|
||||
this.TargetIndex = 0;
|
||||
if (ServerIndex >= 0 && ServerIndex < this.Servers.Count)
|
||||
{
|
||||
string url = $"{this.Servers[ServerIndex].TrimEnd('/')}/api/v1/search?type=archive";
|
||||
if (!string.IsNullOrWhiteSpace(Prefix))
|
||||
{
|
||||
url = $"{url}&q={HttpUtility.UrlEncode(Prefix.TrimEnd('.'))}.";
|
||||
}
|
||||
var window = await WeakReferenceMessenger.Default.Send(new GetWindowMessage());
|
||||
if (window is not null && window.DataContext is MainWindowViewModel mwvm)
|
||||
{
|
||||
int page = 0;
|
||||
bool hadany = false;
|
||||
do
|
||||
{
|
||||
var body = await mwvm.Client.GetStringAsync($"{url}&offset={page}");
|
||||
page++;
|
||||
var res = JsonConvert.DeserializeObject<PackageManagerViewModel.SearchResult>(body);
|
||||
if (res is not null)
|
||||
{
|
||||
hadany = res.Packages.Count > 0;
|
||||
foreach (var item in res.Packages)
|
||||
{
|
||||
string name = item.Name;
|
||||
if (!string.IsNullOrWhiteSpace(Prefix))
|
||||
{
|
||||
int prefixLen = Prefix.TrimEnd('.').Length + 1;
|
||||
name = name.Substring(prefixLen);
|
||||
}
|
||||
|
||||
Targets.Add(new Target(name, name));
|
||||
}
|
||||
}
|
||||
} while (hadany);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task PublishAsync()
|
||||
{
|
||||
|
||||
string ident = Targets[TargetIndex].Real;
|
||||
await CrossLangShell.PublishAsync(Path, ident, Prefix, OutputType == 0 ? Output : "");
|
||||
|
||||
void Tar(Stream strm)
|
||||
{
|
||||
|
||||
string dir = System.IO.Path.Combine(Path, "publish", ident);
|
||||
|
||||
|
||||
using (var tarArchive = TarArchive.CreateOutputTarArchive(strm, Encoding.UTF8))
|
||||
{
|
||||
tarArchive.RootPath = System.IO.Path.DirectorySeparatorChar == '/' ? dir : dir.Replace('\\', '/');
|
||||
if (tarArchive.RootPath.EndsWith("/"))
|
||||
tarArchive.RootPath = tarArchive.RootPath.Remove(tarArchive.RootPath.Length - 1);
|
||||
|
||||
DirectoryContents(tarArchive, dir);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
TarEntry ent = TarEntry.CreateEntryFromFile();
|
||||
ent.TarHeader.Mode = 0755;
|
||||
ent.TarHeader.UserId = 1000;
|
||||
ent.TarHeader.GroupId = 1000;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
if (OutputType > 0)
|
||||
{
|
||||
switch (OutputType)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
FastZip z = new FastZip();
|
||||
z.CreateZip(Output, System.IO.Path.Combine(Path, "publish", ident), true, null);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
using (var strm = File.Create(Output))
|
||||
Tar(strm);
|
||||
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
using (var strm = File.Create(Output))
|
||||
{
|
||||
using (var gz = new GZipOutputStream(strm))
|
||||
Tar(gz);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
using (var strm = File.Create(Output))
|
||||
{
|
||||
using (var bzip2 = new BZip2OutputStream(strm))
|
||||
Tar(bzip2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ = WeakReferenceMessenger.Default.Send(new PublishCloseMessage());
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Cancel()
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send(new PublishCloseMessage());
|
||||
}
|
||||
|
||||
private void DirectoryContents(TarArchive tarArchive, string src)
|
||||
{
|
||||
TarEntry tarEntry = TarEntry.CreateEntryFromFile(src);
|
||||
tarArchive.WriteEntry(tarEntry, false);
|
||||
|
||||
// Write each file to the tar.
|
||||
string[] filenames = Directory.GetFiles(src);
|
||||
foreach (string filename in filenames)
|
||||
{
|
||||
tarEntry = TarEntry.CreateEntryFromFile(filename);
|
||||
|
||||
tarEntry.TarHeader.UserId = 1000;
|
||||
tarEntry.TarHeader.GroupId = 1000;
|
||||
tarArchive.WriteEntry(tarEntry, true);
|
||||
|
||||
}
|
||||
string[] directories = Directory.GetDirectories(src);
|
||||
foreach (string directory in directories)
|
||||
DirectoryContents(tarArchive, directory);
|
||||
}
|
||||
}
|
||||
|
||||
public class Target(string real, string pretty)
|
||||
{
|
||||
public string Real => real;
|
||||
|
||||
public string Pretty => pretty;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Pretty;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user