- add: ContentView think
This commit is contained in:
BIN
Nebula.Launcher/Assets/back.png
Normal file
BIN
Nebula.Launcher/Assets/back.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
BIN
Nebula.Launcher/Assets/dir.png
Normal file
BIN
Nebula.Launcher/Assets/dir.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
Nebula.Launcher/Assets/file.png
Normal file
BIN
Nebula.Launcher/Assets/file.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
Nebula.Launcher/Assets/go.png
Normal file
BIN
Nebula.Launcher/Assets/go.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -1,48 +1,351 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Frozen;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Avalonia.Media;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
|
using Avalonia.Platform;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Nebula.Launcher.ViewHelper;
|
using Nebula.Launcher.ViewHelper;
|
||||||
using Nebula.Launcher.Views.Pages;
|
using Nebula.Launcher.Views.Pages;
|
||||||
|
using Nebula.Shared;
|
||||||
using Nebula.Shared.Models;
|
using Nebula.Shared.Models;
|
||||||
|
using Nebula.Shared.Services;
|
||||||
|
using Nebula.Shared.Utils;
|
||||||
|
|
||||||
namespace Nebula.Launcher.ViewModels;
|
namespace Nebula.Launcher.ViewModels;
|
||||||
|
|
||||||
[ViewModelRegister(typeof(ContentBrowserView))]
|
[ViewModelRegister(typeof(ContentBrowserView))]
|
||||||
public sealed partial class ContentBrowserViewModel : ViewModelBase
|
public sealed partial class ContentBrowserViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
public ObservableCollection<ContentEntry> Entries = new();
|
private readonly IServiceProvider _provider;
|
||||||
|
private readonly ContentService _contentService;
|
||||||
|
private readonly CancellationService _cancellationService;
|
||||||
|
private readonly DebugService _debugService;
|
||||||
|
private readonly PopupMessageService _popupService;
|
||||||
|
public ObservableCollection<ContentEntry> Entries { get; } = new();
|
||||||
|
private readonly List<ContentEntry> _root = new();
|
||||||
|
|
||||||
|
private List<string> _history = new();
|
||||||
|
|
||||||
[ObservableProperty] private string _message = "";
|
[ObservableProperty] private string _message = "";
|
||||||
[ObservableProperty] private string _searchText = "";
|
[ObservableProperty] private string _searchText = "";
|
||||||
|
|
||||||
|
private ContentEntry? _selectedEntry;
|
||||||
|
|
||||||
|
public ContentEntry? SelectedEntry
|
||||||
|
{
|
||||||
|
get => _selectedEntry;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_selectedEntry = value;
|
||||||
|
Entries.Clear();
|
||||||
|
|
||||||
|
Console.WriteLine("Entries clear!");
|
||||||
|
|
||||||
|
if(value == null) return;
|
||||||
|
|
||||||
|
foreach (var (_,entryCh) in value.Childs)
|
||||||
|
{
|
||||||
|
Entries.Add(entryCh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public ContentBrowserViewModel() : base()
|
public ContentBrowserViewModel() : base()
|
||||||
{
|
{
|
||||||
|
var a = new ContentEntry(this, "A:", "");
|
||||||
|
var b = new ContentEntry(this, "B", "");
|
||||||
|
a.TryAddChild(b);
|
||||||
|
Entries.Add(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContentBrowserViewModel(IServiceProvider provider) : base(provider)
|
public ContentBrowserViewModel(IServiceProvider provider, ContentService contentService, CancellationService cancellationService,
|
||||||
|
FileService fileService, HubService hubService, DebugService debugService, PopupMessageService popupService) : base(provider)
|
||||||
{
|
{
|
||||||
|
_provider = provider;
|
||||||
|
_contentService = contentService;
|
||||||
|
_cancellationService = cancellationService;
|
||||||
|
_debugService = debugService;
|
||||||
|
_popupService = popupService;
|
||||||
|
|
||||||
|
hubService.HubServerChangedEventArgs += HubServerChangedEventArgs;
|
||||||
|
hubService.HubServerLoaded += GoHome;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GoHome()
|
||||||
|
{
|
||||||
|
SelectedEntry = null;
|
||||||
|
foreach (var entry in _root)
|
||||||
|
{
|
||||||
|
Entries.Add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HubServerChangedEventArgs(HubServerChangedEventArgs obj)
|
||||||
|
{
|
||||||
|
if(obj.Action == HubServerChangeAction.Clear) _root.Clear();
|
||||||
|
if (obj.Action == HubServerChangeAction.Add)
|
||||||
|
{
|
||||||
|
foreach (var info in obj.Items)
|
||||||
|
{
|
||||||
|
_root.Add(new ContentEntry(this, ToContentUrl(info.Address.ToRobustUrl()),info.Address));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void Go(ContentPath path)
|
||||||
|
{
|
||||||
|
if (path.Pathes.Count == 0)
|
||||||
|
{
|
||||||
|
SearchText = "";
|
||||||
|
GoHome();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.Pathes[0] != "content:" || path.Pathes.Count < 3)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchText = path.Path;
|
||||||
|
|
||||||
|
path.Pathes.RemoveAt(0);
|
||||||
|
path.Pathes.RemoveAt(0);
|
||||||
|
|
||||||
|
var serverUrl = path.Pathes[0];
|
||||||
|
path.Pathes.RemoveAt(0);
|
||||||
|
|
||||||
|
_debugService.Debug(path.Path + " " + serverUrl +" "+ SelectedEntry?.ServerName);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ContentEntry entry;
|
||||||
|
if (serverUrl == SelectedEntry?.ServerName)
|
||||||
|
entry = SelectedEntry.GetRoot();
|
||||||
|
else
|
||||||
|
entry = await CreateEntry(serverUrl);
|
||||||
|
|
||||||
|
if (!entry.TryGetEntry(path, out var centry))
|
||||||
|
{
|
||||||
|
throw new Exception("Not found!");
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectedEntry = centry;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
_popupService.Popup(e);
|
||||||
|
//throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void OnBackEnter()
|
public void OnBackEnter()
|
||||||
{
|
{
|
||||||
|
Go(new ContentPath(GetHistory()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnGoEnter()
|
public void OnGoEnter()
|
||||||
{
|
{
|
||||||
|
Go(new ContentPath(SearchText));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<ContentEntry> CreateEntry(string serverUrl)
|
||||||
|
{
|
||||||
|
var rurl = serverUrl.ToRobustUrl();
|
||||||
|
var info = await _contentService.GetBuildInfo(rurl, _cancellationService.Token);
|
||||||
|
var loading = _provider.GetService<LoadingContextViewModel>()!;
|
||||||
|
loading.LoadingName = "Loading entry";
|
||||||
|
_popupService.Popup(loading);
|
||||||
|
var items = await _contentService.EnsureItems(info.RobustManifestInfo, loading,
|
||||||
|
_cancellationService.Token);
|
||||||
|
|
||||||
|
var rootEntry = new ContentEntry(this,ToContentUrl(rurl), serverUrl);
|
||||||
|
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
var path = new ContentPath(item.Path);
|
||||||
|
rootEntry.CreateItem(path, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.Dispose();
|
||||||
|
|
||||||
|
return rootEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AppendHistory(string str)
|
||||||
|
{
|
||||||
|
if(_history.Count >= 10) _history.RemoveAt(9);
|
||||||
|
_history.Insert(0, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetHistory()
|
||||||
|
{
|
||||||
|
if (_history.Count == 0) return "";
|
||||||
|
var h = _history[0];
|
||||||
|
_history.RemoveAt(0);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ToContentUrl(RobustUrl serverUrl)
|
||||||
|
{
|
||||||
|
var port = serverUrl.Uri.Port != -1 ? (":"+serverUrl.Uri.Port) : "";
|
||||||
|
return "content://" + serverUrl.Uri.Host + port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ContentEntry
|
public class ContentEntry
|
||||||
{
|
{
|
||||||
|
private readonly ContentBrowserViewModel _viewModel;
|
||||||
|
|
||||||
|
public static IImage DirImage = new Bitmap(AssetLoader.Open(new Uri("avares://Nebula.Launcher/Assets/dir.png")));
|
||||||
|
public static IImage IconImage = new Bitmap(AssetLoader.Open(new Uri("avares://Nebula.Launcher/Assets/file.png")));
|
||||||
|
|
||||||
|
public RobustManifestItem? Item;
|
||||||
|
public bool IsDirectory => Item == null;
|
||||||
|
|
||||||
|
public string Name { get; private set; }
|
||||||
|
public string ServerName { get; private set; }
|
||||||
|
public IImage IconPath { get; set; } = DirImage;
|
||||||
|
|
||||||
|
public ContentEntry? Parent { get; private set; }
|
||||||
|
public bool IsRoot => Parent == null;
|
||||||
|
|
||||||
|
private readonly Dictionary<string, ContentEntry> _childs = new();
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<string, ContentEntry> Childs => _childs.ToFrozenDictionary();
|
||||||
|
|
||||||
|
public bool TryGetChild(string name,[NotNullWhen(true)] out ContentEntry? child)
|
||||||
|
{
|
||||||
|
return _childs.TryGetValue(name, out child);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryAddChild(ContentEntry contentEntry)
|
||||||
|
{
|
||||||
|
if(_childs.TryAdd(contentEntry.Name, contentEntry))
|
||||||
|
{
|
||||||
|
contentEntry.Parent = this;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ContentEntry(ContentBrowserViewModel viewModel, string name, string serverName)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
ServerName = serverName;
|
||||||
|
_viewModel = viewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentPath GetPath()
|
||||||
|
{
|
||||||
|
if (Parent != null)
|
||||||
|
{
|
||||||
|
var path = Parent.GetPath();
|
||||||
|
path.Pathes.Add(Name);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
return new ContentPath(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentEntry GetOrCreateDirectory(ContentPath rootPath)
|
||||||
|
{
|
||||||
|
if (rootPath.Pathes.Count == 0) return this;
|
||||||
|
|
||||||
|
var fName = rootPath.Pathes[0];
|
||||||
|
rootPath.Pathes.RemoveAt(0);
|
||||||
|
|
||||||
|
if(!TryGetChild(fName, out var child))
|
||||||
|
{
|
||||||
|
child = new ContentEntry(_viewModel, fName, ServerName);
|
||||||
|
TryAddChild(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
return child.GetOrCreateDirectory(rootPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentEntry GetRoot()
|
||||||
|
{
|
||||||
|
if (Parent == null) return this;
|
||||||
|
return Parent.GetRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentEntry CreateItem(ContentPath path, RobustManifestItem item)
|
||||||
|
{
|
||||||
|
var dir = path.GetDirectory();
|
||||||
|
var dirEntry = GetOrCreateDirectory(dir);
|
||||||
|
|
||||||
|
var entry = new ContentEntry(_viewModel, path.GetName(), ServerName)
|
||||||
|
{
|
||||||
|
Item = item
|
||||||
|
};
|
||||||
|
|
||||||
|
dirEntry.TryAddChild(entry);
|
||||||
|
entry.IconPath = IconImage;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetEntry(ContentPath path, out ContentEntry? entry)
|
||||||
|
{
|
||||||
|
entry = null;
|
||||||
|
|
||||||
|
if (path.Pathes.Count == 0)
|
||||||
|
{
|
||||||
|
entry = this;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fName = path.Pathes[0];
|
||||||
|
path.Pathes.RemoveAt(0);
|
||||||
|
|
||||||
|
if(!TryGetChild(fName, out var child))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return child.TryGetEntry(path, out entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnPathGo()
|
||||||
|
{
|
||||||
|
_viewModel.Go(GetPath());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ContentPath
|
public struct ContentPath
|
||||||
{
|
{
|
||||||
public RobustUrl ServerUrl;
|
public List<string> Pathes;
|
||||||
}
|
|
||||||
|
public ContentPath(List<string> pathes)
|
||||||
|
{
|
||||||
|
Pathes = pathes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentPath(string path)
|
||||||
|
{
|
||||||
|
Pathes = path.Split("/").ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentPath GetDirectory()
|
||||||
|
{
|
||||||
|
var p = Pathes.ToList();
|
||||||
|
p.RemoveAt(Pathes.Count - 1);
|
||||||
|
return new ContentPath(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return Pathes.Last();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Path => string.Join("/", Pathes);
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ public partial class MainViewModel : ViewModelBase
|
|||||||
private readonly List<ListItemTemplate> _templates =
|
private readonly List<ListItemTemplate> _templates =
|
||||||
[
|
[
|
||||||
new ListItemTemplate(typeof(AccountInfoViewModel), "Account", "Account"),
|
new ListItemTemplate(typeof(AccountInfoViewModel), "Account", "Account"),
|
||||||
new ListItemTemplate(typeof(ServerListViewModel), "HomeRegular", "Servers")
|
new ListItemTemplate(typeof(ServerListViewModel), "HomeRegular", "Servers"),
|
||||||
|
new ListItemTemplate(typeof(ContentBrowserViewModel), "HomeRegular", "Content")
|
||||||
];
|
];
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
|
|||||||
@@ -34,9 +34,15 @@ public partial class ServerListViewModel : ViewModelBase
|
|||||||
_serviceProvider = serviceProvider;
|
_serviceProvider = serviceProvider;
|
||||||
_hubService = hubService;
|
_hubService = hubService;
|
||||||
hubService.HubServerChangedEventArgs += HubServerChangedEventArgs;
|
hubService.HubServerChangedEventArgs += HubServerChangedEventArgs;
|
||||||
|
hubService.HubServerLoaded += HubServerLoaded;
|
||||||
OnSearchChange += OnChangeSearch;
|
OnSearchChange += OnChangeSearch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HubServerLoaded()
|
||||||
|
{
|
||||||
|
SortServers();
|
||||||
|
}
|
||||||
|
|
||||||
private void OnChangeSearch()
|
private void OnChangeSearch()
|
||||||
{
|
{
|
||||||
SortServers();
|
SortServers();
|
||||||
@@ -62,8 +68,6 @@ public partial class ServerListViewModel : ViewModelBase
|
|||||||
{
|
{
|
||||||
UnsortedServers.Clear();
|
UnsortedServers.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
SortServers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SortServers()
|
private void SortServers()
|
||||||
|
|||||||
@@ -1,39 +1,69 @@
|
|||||||
<UserControl xmlns="https://github.com/avaloniaui"
|
<UserControl
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
d:DesignHeight="450"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
d:DesignWidth="800"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
mc:Ignorable="d"
|
||||||
xmlns:viewModels="clr-namespace:Nebula.Launcher.ViewModels"
|
x:Class="Nebula.Launcher.Views.Pages.ContentBrowserView"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
x:DataType="viewModels:ContentBrowserViewModel"
|
||||||
x:Class="Nebula.Launcher.Views.Pages.ContentBrowserView"
|
xmlns="https://github.com/avaloniaui"
|
||||||
x:DataType="viewModels:ContentBrowserViewModel">
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:viewModels="clr-namespace:Nebula.Launcher.ViewModels"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
<Design.DataContext>
|
<Design.DataContext>
|
||||||
<viewModels:ContentBrowserViewModel />
|
<viewModels:ContentBrowserViewModel />
|
||||||
</Design.DataContext>
|
</Design.DataContext>
|
||||||
|
|
||||||
<StackPanel>
|
<StackPanel Margin="5">
|
||||||
<Border
|
<Border BorderThickness="2,0,0,0" CornerRadius="10">
|
||||||
BorderThickness="2,0,0,0"
|
|
||||||
CornerRadius="10"
|
|
||||||
Grid.Row="1">
|
|
||||||
<Grid ColumnDefinitions="*,40,40" RowDefinitions="*">
|
<Grid ColumnDefinitions="*,40,40" RowDefinitions="*">
|
||||||
<TextBox
|
<TextBox
|
||||||
Margin="0"
|
Margin="0"
|
||||||
Text="{Binding SearchText}"
|
Text="{Binding SearchText}"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Watermark="Server name..." />
|
Watermark="Path..." />
|
||||||
<Button
|
<Button
|
||||||
Command="{Binding OnBackEnter}"
|
Command="{Binding OnBackEnter}"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Padding="10">
|
Padding="10">
|
||||||
<Image Source="/Assets/filter.png" />
|
<Image Source="/Assets/back.png" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
Command="{Binding OnGoEnter}"
|
Command="{Binding OnGoEnter}"
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
Padding="10">
|
Padding="10">
|
||||||
<Image Source="/Assets/refresh.png" />
|
<Image Source="/Assets/go.png" />
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
<ScrollViewer Margin="0,5,10,5">
|
||||||
|
<ItemsControl
|
||||||
|
Background="#00000000"
|
||||||
|
ItemsSource="{Binding Entries}"
|
||||||
|
Padding="0">
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate DataType="{x:Type viewModels:ContentEntry}">
|
||||||
|
<Button
|
||||||
|
Command="{Binding OnPathGo}"
|
||||||
|
CornerRadius="0"
|
||||||
|
HorizontalAlignment="Stretch">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="15">
|
||||||
|
<Border
|
||||||
|
Background="#00000000"
|
||||||
|
BorderThickness="0,0,2,0"
|
||||||
|
CornerRadius="0">
|
||||||
|
<Image
|
||||||
|
Height="15"
|
||||||
|
Margin="10,0,10,0"
|
||||||
|
Source="{Binding IconPath}" />
|
||||||
|
</Border>
|
||||||
|
<Label>
|
||||||
|
<TextBlock Text="{Binding Name}" />
|
||||||
|
</Label>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</ScrollViewer>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -15,7 +15,10 @@
|
|||||||
<viewModels:ServerListViewModel />
|
<viewModels:ServerListViewModel />
|
||||||
</Design.DataContext>
|
</Design.DataContext>
|
||||||
|
|
||||||
<Grid ColumnDefinitions="*" RowDefinitions="*,40" Margin="15">
|
<Grid
|
||||||
|
ColumnDefinitions="*"
|
||||||
|
Margin="5"
|
||||||
|
RowDefinitions="*,40">
|
||||||
<ScrollViewer Margin="0,0,0,10" Padding="0,0,8,0">
|
<ScrollViewer Margin="0,0,0,10" Padding="0,0,8,0">
|
||||||
<ItemsControl
|
<ItemsControl
|
||||||
Background="#00000000"
|
Background="#00000000"
|
||||||
@@ -122,29 +125,32 @@
|
|||||||
<Panel Grid.Column="1" Grid.Row="1">
|
<Panel Grid.Column="1" Grid.Row="1">
|
||||||
<Button
|
<Button
|
||||||
Command="{Binding RunInstance}"
|
Command="{Binding RunInstance}"
|
||||||
IsVisible="{Binding RunVisible}"
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
CornerRadius="10,0,10,10"
|
CornerRadius="10,0,10,10"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
IsVisible="{Binding RunVisible}"
|
||||||
VerticalAlignment="Stretch">
|
VerticalAlignment="Stretch">
|
||||||
<Label HorizontalAlignment="Center" VerticalAlignment="Center">
|
<Label HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||||
Play
|
Play
|
||||||
</Label>
|
</Label>
|
||||||
</Button>
|
</Button>
|
||||||
<Grid Grid.ColumnDefinitions="*,*" IsVisible="{Binding !RunVisible}">
|
<Grid Grid.ColumnDefinitions="*,*" IsVisible="{Binding !RunVisible}">
|
||||||
<Button Command="{Binding ReadLog}"
|
<Button
|
||||||
CornerRadius="10,0,0,10"
|
Command="{Binding ReadLog}"
|
||||||
Margin="0,0,1,0"
|
CornerRadius="10,0,0,10"
|
||||||
VerticalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
HorizontalAlignment="Stretch">
|
Margin="0,0,1,0"
|
||||||
|
VerticalAlignment="Stretch">
|
||||||
<Label HorizontalAlignment="Center" VerticalAlignment="Center">
|
<Label HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||||
Log
|
Log
|
||||||
</Label>
|
</Label>
|
||||||
</Button>
|
</Button>
|
||||||
<Button Grid.Column="1" HorizontalAlignment="Stretch"
|
<Button
|
||||||
CornerRadius="0,0,10,0"
|
Command="{Binding StopInstance}"
|
||||||
Margin="1,0,0,0"
|
CornerRadius="0,0,10,0"
|
||||||
VerticalAlignment="Stretch"
|
Grid.Column="1"
|
||||||
Command="{Binding StopInstance}">
|
HorizontalAlignment="Stretch"
|
||||||
|
Margin="1,0,0,0"
|
||||||
|
VerticalAlignment="Stretch">
|
||||||
<Label HorizontalAlignment="Center" VerticalAlignment="Center">
|
<Label HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||||
Stop
|
Stop
|
||||||
</Label>
|
</Label>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ public class HubService
|
|||||||
private readonly RestService _restService;
|
private readonly RestService _restService;
|
||||||
|
|
||||||
public Action<HubServerChangedEventArgs>? HubServerChangedEventArgs;
|
public Action<HubServerChangedEventArgs>? HubServerChangedEventArgs;
|
||||||
|
public Action? HubServerLoaded;
|
||||||
|
|
||||||
private bool _isUpdating = false;
|
private bool _isUpdating = false;
|
||||||
public HubService(ConfigurationService configurationService, RestService restService)
|
public HubService(ConfigurationService configurationService, RestService restService)
|
||||||
@@ -35,6 +36,7 @@ public class HubService
|
|||||||
}
|
}
|
||||||
|
|
||||||
_isUpdating = false;
|
_isUpdating = false;
|
||||||
|
HubServerLoaded?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user