mirror of
https://onedev.site.tesses.net/crosslang/crosslangdevstudio
synced 2026-02-08 09:15:45 +00:00
888 lines
27 KiB
C#
888 lines
27 KiB
C#
using System;
|
|
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;
|
|
|
|
public partial class MainWindowViewModel : ViewModelBase
|
|
{
|
|
|
|
public HttpClient Client { get; set; } = new();
|
|
public string CurrentProject { get; set; } = "";
|
|
public Func<object> NewItemFactory => AddItem;
|
|
|
|
|
|
public ObservableCollection<TabItemViewModel> TabItems { get; } = new();
|
|
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
|
|
{
|
|
get
|
|
{
|
|
return new TabItemViewModel()
|
|
{
|
|
Header = "Welcome",
|
|
Body = new WelcomeViewModel(this)
|
|
};
|
|
}
|
|
}
|
|
private ProjectFileNode? _selectedProjectFile = null;
|
|
|
|
public ProjectFileNode? SelectedProjectFile
|
|
{
|
|
get => _selectedProjectFile;
|
|
set
|
|
{
|
|
_selectedProjectFile = value;
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
private object AddItem()
|
|
{
|
|
var tab = new TabItemViewModel
|
|
{
|
|
Header = "New Tab",
|
|
|
|
};
|
|
if (Directory.Exists(CurrentProject))
|
|
{
|
|
var newTabItem = new NewTabViewModel(this, tab);
|
|
tab.Body = newTabItem;
|
|
}
|
|
|
|
|
|
|
|
return tab;
|
|
}
|
|
|
|
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]
|
|
public void RefreshListing()
|
|
{
|
|
if (!File.Exists(Path.Combine(CurrentProject, "cross.json")))
|
|
{
|
|
return;
|
|
}
|
|
Refresh(CurrentProject);
|
|
}
|
|
|
|
private void Refresh(string obj)
|
|
{
|
|
|
|
|
|
|
|
for (int i = 0; i < TabItems.Count; i++)
|
|
{
|
|
if (TabItems[i].Body is WelcomeViewModel)
|
|
{
|
|
TabItems.RemoveAt(i);
|
|
i--;
|
|
}
|
|
|
|
}
|
|
|
|
ObservableCollection<ProjectFileNode> entries = new ObservableCollection<ProjectFileNode>
|
|
{
|
|
new ProjectFileNode("Project",[
|
|
new ProjectFileNode("Configuration",()=>{
|
|
|
|
OpenProjectConfig();
|
|
}),
|
|
new ProjectFileNode("Project Packages", ()=>{
|
|
OpenProjectPackages();
|
|
}),
|
|
new ProjectFileNode("Project Dependencies (folders)",()=>{
|
|
OpenProjectDependencies();
|
|
})
|
|
])
|
|
|
|
};
|
|
|
|
void Itterate(ObservableCollection<ProjectFileNode> nodes, string dir)
|
|
{
|
|
|
|
foreach (var item in Directory.EnumerateDirectories(dir))
|
|
{
|
|
ObservableCollection<ProjectFileNode> files = new();
|
|
Itterate(files, item);
|
|
var pfn = new ProjectFileNode(Path.GetFileName(item), files);
|
|
nodes.Add(pfn);
|
|
}
|
|
foreach (var item in Directory.EnumerateFiles(dir))
|
|
{
|
|
nodes.Add(new ProjectFileNode(Path.GetFileName(item), () =>
|
|
{
|
|
OpenFile(item);
|
|
}));
|
|
}
|
|
|
|
}
|
|
Itterate(entries, obj);
|
|
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))
|
|
{
|
|
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()
|
|
{
|
|
|
|
if (Directory.Exists(CurrentProject))
|
|
{
|
|
var config = Path.Combine(CurrentProject, "cross.json");
|
|
foreach (var item in TabItems)
|
|
{
|
|
if (item.Body is ProjectConfigurationViewModel model && model.FilePath == config)
|
|
{
|
|
SelectedTab = item;
|
|
return;
|
|
}
|
|
}
|
|
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 = {
|
|
".tcross",
|
|
".json",
|
|
".txt",
|
|
".cpp",
|
|
".hpp",
|
|
".html",
|
|
".css",
|
|
".webmanifest",
|
|
".cs",
|
|
".c",
|
|
".h",
|
|
".xml",
|
|
".xaml",
|
|
".js",
|
|
".jsx",
|
|
".ts",
|
|
".tsx",
|
|
".gitignore",
|
|
".svg",
|
|
".md",
|
|
".yaml",
|
|
".yml",
|
|
".toml",
|
|
".tcasm",
|
|
".dart",
|
|
".bat",
|
|
".sh",
|
|
".lua",
|
|
".java",
|
|
".ini",
|
|
".go",
|
|
".crossarchiveignore"
|
|
};
|
|
|
|
public void OpenFile(string path)
|
|
{
|
|
bool isValid = false;
|
|
string ext = Path.GetExtension(path).ToLower();
|
|
|
|
foreach (var item in FILE_EXTS)
|
|
{
|
|
if (ext == item)
|
|
isValid = true;
|
|
}
|
|
if (Path.GetFileNameWithoutExtension(path).ToLower() == "dockerfile")
|
|
isValid = true;
|
|
if (Path.GetFileNameWithoutExtension(path).ToLower() == "makefile")
|
|
isValid = true;
|
|
|
|
if (!isValid)
|
|
{
|
|
OpenOtherFile(path, ext);
|
|
return;
|
|
}
|
|
|
|
foreach (var item in TabItems)
|
|
{
|
|
if (item.Body is FileEditorViewModel model)
|
|
{
|
|
if (model.FilePath == path)
|
|
{
|
|
SelectedTab = item;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
var tab = new TabItemViewModel
|
|
{
|
|
Header = Path.GetFileName(path),
|
|
|
|
};
|
|
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)
|
|
{
|
|
TabItems.Add(item);
|
|
SelectedTab = item;
|
|
|
|
}
|
|
[RelayCommand]
|
|
public async Task NewProjectAsync()
|
|
{
|
|
var res = await WeakReferenceMessenger.Default.Send(new NewProjectMessage());
|
|
if (!string.IsNullOrWhiteSpace(res))
|
|
{
|
|
LoadProject(res);
|
|
}
|
|
}
|
|
[RelayCommand]
|
|
public async Task OpenProjectAsync()
|
|
{
|
|
var opts = new FolderPickerOpenOptions();
|
|
opts.AllowMultiple = false;
|
|
opts.Title = "Open Project";
|
|
|
|
var window = await WeakReferenceMessenger.Default.Send(new GetWindowMessage());
|
|
opts.SuggestedStartLocation = await window.StorageProvider.TryGetFolderFromPathAsync(CrossLangShell.Settings.ProjectDirectory) ?? null;
|
|
var res = await window.StorageProvider.OpenFolderPickerAsync(opts);
|
|
if (res.Count == 1)
|
|
{
|
|
var url = res[0].TryGetLocalPath();
|
|
if (!string.IsNullOrWhiteSpace(url))
|
|
{
|
|
LoadProject(url);
|
|
}
|
|
}
|
|
}
|
|
|
|
[RelayCommand]
|
|
private void OpenProjectInFileManager()
|
|
{
|
|
if (Directory.Exists(CurrentProject))
|
|
{
|
|
CrossLangShell.OpenFolderInFileManager(CurrentProject);
|
|
}
|
|
}
|
|
[RelayCommand]
|
|
private void OpenProjectInTerminal()
|
|
{
|
|
if (Directory.Exists(CurrentProject))
|
|
{
|
|
CrossLangShell.OpenTerminalInFolder(CurrentProject);
|
|
}
|
|
}
|
|
[RelayCommand]
|
|
private void BuildAndRun()
|
|
{
|
|
SaveAll();
|
|
if (Directory.Exists(CurrentProject))
|
|
{
|
|
CrossLangShell.RunProjectInFolder(CurrentProject);
|
|
}
|
|
}
|
|
[RelayCommand]
|
|
private void Build()
|
|
{
|
|
SaveAll();
|
|
if (Directory.Exists(CurrentProject))
|
|
{
|
|
CrossLangShell.BuildProjectInFolder(CurrentProject);
|
|
}
|
|
}
|
|
|
|
[RelayCommand]
|
|
private void Save()
|
|
{
|
|
SelectedTab?.Save();
|
|
}
|
|
[RelayCommand]
|
|
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
|
|
{
|
|
private MainWindowViewModel mainWindowViewModel;
|
|
private TabItemViewModel tab;
|
|
|
|
public NewTabViewModel(MainWindowViewModel mainWindowViewModel, TabItemViewModel tab)
|
|
{
|
|
this.mainWindowViewModel = mainWindowViewModel;
|
|
this.tab = tab;
|
|
}
|
|
|
|
[ObservableProperty]
|
|
private string _filePath = "src/";
|
|
|
|
[ObservableProperty]
|
|
private decimal _progress = 0;
|
|
|
|
[ObservableProperty]
|
|
private string _url = "";
|
|
|
|
[RelayCommand]
|
|
private void CreateDirectory()
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(FilePath))
|
|
{
|
|
Directory.CreateDirectory(Path.Combine(mainWindowViewModel.CurrentProject, FilePath));
|
|
mainWindowViewModel.RefreshListing();
|
|
mainWindowViewModel.TabItems.Remove(tab);
|
|
}
|
|
}
|
|
[RelayCommand]
|
|
private void CreateFile()
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(FilePath))
|
|
{
|
|
var path = Path.Combine(mainWindowViewModel.CurrentProject, FilePath);
|
|
File.WriteAllText(path, "");
|
|
mainWindowViewModel.RefreshListing();
|
|
mainWindowViewModel.TabItems.Remove(tab);
|
|
mainWindowViewModel.OpenFile(path);
|
|
}
|
|
}
|
|
|
|
[RelayCommand]
|
|
private async Task DownloadFileAsync()
|
|
{
|
|
try
|
|
{
|
|
using var destStrm = File.Create(Path.Combine(mainWindowViewModel.CurrentProject, FilePath));
|
|
var res = await mainWindowViewModel.Client.GetAsync(Url);
|
|
long length = 0;
|
|
long offset = 0;
|
|
Progress = 0;
|
|
if (res.IsSuccessStatusCode)
|
|
{
|
|
if (res.Content.Headers.ContentLength.HasValue)
|
|
{
|
|
length = res.Content.Headers.ContentLength.Value;
|
|
byte[] array = new byte[1024];
|
|
int read = 0;
|
|
using var src = await res.Content.ReadAsStreamAsync();
|
|
do
|
|
{
|
|
read = await src.ReadAsync(array);
|
|
await destStrm.WriteAsync(array, 0, read);
|
|
offset += read;
|
|
if (length > 0)
|
|
{
|
|
Progress = (decimal)offset / (decimal)length;
|
|
}
|
|
|
|
} while (read != 0);
|
|
}
|
|
else
|
|
{
|
|
await res.Content.CopyToAsync(destStrm);
|
|
}
|
|
Progress = 1;
|
|
mainWindowViewModel.RefreshListing();
|
|
mainWindowViewModel.TabItems.Remove(tab);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception();
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
File.Delete(FilePath);
|
|
this.Url = $"FAILED: {this.Url}";
|
|
}
|
|
|
|
}
|
|
} |