- add: popup message

This commit is contained in:
2024-12-26 18:54:37 +03:00
parent a389dd5481
commit 516801840c
14 changed files with 367 additions and 70 deletions

View File

@@ -15,6 +15,8 @@
<entry key="Nebula.Launcher/Views/Pages/AccountInfoView.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" /> <entry key="Nebula.Launcher/Views/Pages/AccountInfoView.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" />
<entry key="Nebula.Launcher/Views/Pages/ServerListPage.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" /> <entry key="Nebula.Launcher/Views/Pages/ServerListPage.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" />
<entry key="Nebula.Launcher/Views/Pages/ServerListView.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" /> <entry key="Nebula.Launcher/Views/Pages/ServerListView.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" />
<entry key="Nebula.Launcher/Views/Popup/InfoPopupView.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" />
<entry key="Nebula.Launcher/Views/Popup/MessagePopupView.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" />
<entry key="Nebula.Launcher/Views/ServerContainer.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" /> <entry key="Nebula.Launcher/Views/ServerContainer.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" />
<entry key="Nebula.Launcher/Views/ServerList.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" /> <entry key="Nebula.Launcher/Views/ServerList.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" />
<entry key="Nebula.Launcher/Views/Tabs/AccountInfoTab.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" /> <entry key="Nebula.Launcher/Views/Tabs/AccountInfoTab.axaml" value="Nebula.Launcher/Nebula.Launcher.csproj" />

View File

@@ -85,9 +85,11 @@ public static class ServiceCollectionExtensions
public sealed class ServiceRegisterAttribute : Attribute public sealed class ServiceRegisterAttribute : Attribute
{ {
public Type? Inference { get; } public Type? Inference { get; }
public bool IsSingleton { get; }
public ServiceRegisterAttribute(Type? inference = null) public ServiceRegisterAttribute(Type? inference = null, bool isSingleton = true)
{ {
IsSingleton = isSingleton;
Inference = inference; Inference = inference;
} }
} }

View File

@@ -2,12 +2,15 @@ using System;
namespace Nebula.Launcher.ViewHelper; namespace Nebula.Launcher.ViewHelper;
[AttributeUsage(AttributeTargets.Class)]
public class ViewRegisterAttribute : Attribute public class ViewRegisterAttribute : Attribute
{ {
public Type Type { get; } public Type Type { get; }
public bool IsSingleton { get; }
public ViewRegisterAttribute(Type type) public ViewRegisterAttribute(Type type, bool isSingleton = true)
{ {
Type = type; Type = type;
IsSingleton = isSingleton;
} }
} }

View File

@@ -85,12 +85,12 @@ public partial class AccountInfoViewModel : ViewModelBase
} }
} }
internal class Ref<T> public class Ref<T>
{ {
public T Value = default!; public T Value = default!;
} }
internal class DelegateCommand<T> : ICommand public class DelegateCommand<T> : ICommand
{ {
private readonly Action<T> _func; private readonly Action<T> _func;
public readonly Ref<T> TRef = new(); public readonly Ref<T> TRef = new();

View File

@@ -0,0 +1,22 @@
using System;
using CommunityToolkit.Mvvm.ComponentModel;
using Nebula.Launcher.ViewHelper;
using Nebula.Launcher.Views.Popup;
namespace Nebula.Launcher.ViewModels;
[ViewRegister(typeof(InfoPopupView), false)]
public partial class InfoPopupViewModel : PopupViewModelBase
{
public InfoPopupViewModel()
{
}
public InfoPopupViewModel(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
public override string Title => "Info";
[ObservableProperty]
private string _infoText = "Test";
}

View File

@@ -21,19 +21,39 @@ public partial class MainViewModel : ViewModelBase
{ {
TryGetViewModel(typeof(AccountInfoViewModel), out var model); TryGetViewModel(typeof(AccountInfoViewModel), out var model);
_currentPage = model!; _currentPage = model!;
TryGetViewModel(typeof(MessagePopupViewModel), out var viewModelBase);
_messagePopupViewModel = (MessagePopupViewModel)viewModelBase!;
Items = new ObservableCollection<ListItemTemplate>(_templates); Items = new ObservableCollection<ListItemTemplate>(_templates);
SelectedListItem = Items.First(vm => vm.ModelType == typeof(AccountInfoViewModel)); SelectedListItem = Items.First(vm => vm.ModelType == typeof(AccountInfoViewModel));
} }
public MainViewModel(AccountInfoViewModel accountInfoViewModel, IServiceProvider serviceProvider): base(serviceProvider) public MainViewModel(AccountInfoViewModel accountInfoViewModel, MessagePopupViewModel messagePopupViewModel,
IServiceProvider serviceProvider): base(serviceProvider)
{ {
_currentPage = accountInfoViewModel; _currentPage = accountInfoViewModel;
_messagePopupViewModel = messagePopupViewModel;
Items = new ObservableCollection<ListItemTemplate>(_templates); Items = new ObservableCollection<ListItemTemplate>(_templates);
_messagePopupViewModel.OnOpenRequired += () => OnOpenRequired();
_messagePopupViewModel.OnCloseRequired += () => OnCloseRequired();
SelectedListItem = Items.First(vm => vm.ModelType == typeof(AccountInfoViewModel)); SelectedListItem = Items.First(vm => vm.ModelType == typeof(AccountInfoViewModel));
} }
private void OnCloseRequired()
{
IsEnabled = true;
Popup = false;
}
private void OnOpenRequired()
{
IsEnabled = false;
Popup = true;
}
private readonly List<ListItemTemplate> _templates = private readonly List<ListItemTemplate> _templates =
[ [
new ListItemTemplate(typeof(AccountInfoViewModel), "Account", "Account"), new ListItemTemplate(typeof(AccountInfoViewModel), "Account", "Account"),
@@ -46,6 +66,11 @@ public partial class MainViewModel : ViewModelBase
[ObservableProperty] [ObservableProperty]
private ViewModelBase _currentPage; private ViewModelBase _currentPage;
[ObservableProperty] private bool _isEnabled = true;
[ObservableProperty] private bool _popup;
private readonly MessagePopupViewModel _messagePopupViewModel;
[ObservableProperty] [ObservableProperty]
private ListItemTemplate? _selectedListItem; private ListItemTemplate? _selectedListItem;
@@ -59,6 +84,12 @@ public partial class MainViewModel : ViewModelBase
} }
CurrentPage = vmb; CurrentPage = vmb;
var model = GetViewModel<InfoPopupViewModel>();
model.InfoText = "Переключили прикол!";
_messagePopupViewModel.PopupMessage(model);
} }
public ObservableCollection<ListItemTemplate> Items { get; } public ObservableCollection<ListItemTemplate> Items { get; }

View File

@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Input;
using Avalonia.Logging;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Nebula.Launcher.ViewHelper;
using Nebula.Launcher.Views.Popup;
namespace Nebula.Launcher.ViewModels;
[ViewRegister(typeof(MessagePopupView))]
public partial class MessagePopupViewModel : ViewModelBase
{
public MessagePopupViewModel() : base()
{
}
public MessagePopupViewModel(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
public Action? OnCloseRequired;
public Action? OnOpenRequired;
public Queue<PopupViewModelBase> ViewQueue = new();
[ObservableProperty]
private PopupViewModelBase? _currentPopup;
[ObservableProperty]
private string _currentTitle = "Default";
public void PopupMessage(PopupViewModelBase viewModelBase)
{
Console.WriteLine(viewModelBase.Title);
if (CurrentPopup == null)
{
CurrentPopup = viewModelBase;
CurrentTitle = viewModelBase.Title;
OnOpenRequired?.Invoke();
}
else
{
ViewQueue.Enqueue(viewModelBase);
}
}
[RelayCommand]
private void TriggerClose()
{
ClosePopup();
}
[RelayCommand]
private void ClosePopup()
{
Console.WriteLine("Gadeem");
if (!ViewQueue.TryDequeue(out var viewModelBase))
OnCloseRequired?.Invoke();
else
CurrentTitle = viewModelBase.Title;
CurrentPopup = viewModelBase;
}
}

View File

@@ -0,0 +1,16 @@
using System;
namespace Nebula.Launcher.ViewModels;
public abstract class PopupViewModelBase : ViewModelBase
{
public PopupViewModelBase()
{
}
public PopupViewModelBase(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
public abstract string Title { get; }
}

View File

@@ -31,6 +31,19 @@ public abstract class ViewModelBase : ObservableObject
return true; return true;
} }
public bool TryGetViewModel<T>([NotNullWhen(true)] out T? viewModelBase) where T: ViewModelBase
{
var success = TryGetViewModel(typeof(T), out var vmb);
viewModelBase = (T?)vmb;
return success;
}
public T GetViewModel<T>() where T: ViewModelBase
{
TryGetViewModel<T>(out var viewModelBase);
return viewModelBase!;
}
public void AssertDesignMode() public void AssertDesignMode()
{ {
if (!Design.IsDesignMode) throw new Exception(); if (!Design.IsDesignMode) throw new Exception();

View File

@@ -9,75 +9,96 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="clr-namespace:Nebula.Launcher.Models" xmlns:models="clr-namespace:Nebula.Launcher.Models"
xmlns:popup="clr-namespace:Nebula.Launcher.Views.Popup"
xmlns:viewModels="clr-namespace:Nebula.Launcher.ViewModels" xmlns:viewModels="clr-namespace:Nebula.Launcher.ViewModels"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Design.DataContext> <Design.DataContext>
<viewModels:MainViewModel /> <viewModels:MainViewModel />
</Design.DataContext> </Design.DataContext>
<Grid <Panel>
ColumnDefinitions="65,*" <Grid
Margin="0" ColumnDefinitions="65,*"
RowDefinitions="*,40"> IsEnabled="{Binding IsEnabled}"
Margin="0"
RowDefinitions="*,40">
<TransitioningContentControl <TransitioningContentControl
Grid.Column="1" Content="{Binding CurrentPage}"
Grid.Row="0" Grid.Column="1"
Content="{Binding CurrentPage}" /> Grid.Row="0" />
<SplitView <SplitView
Grid.Row="0" Grid.Column="0" CompactPaneLength="65"
Grid.ColumnSpan="2" DisplayMode="CompactInline"
CompactPaneLength="65" Grid.Column="0"
DisplayMode="CompactInline" Grid.ColumnSpan="2"
IsPaneOpen="{Binding IsPaneOpen}" Grid.Row="0"
PaneBackground="#00000000"> IsPaneOpen="{Binding IsPaneOpen}"
<SplitView.Pane> PaneBackground="#00000000">
<Border <SplitView.Pane>
BorderThickness="0,0,2,0" <Border
CornerRadius="0,8,8,0" BorderThickness="0,0,2,0"
Grid.Column="0" CornerRadius="0,8,8,0"
Grid.Row="0" Grid.Column="0"
Margin="0,0,5,0" Grid.Row="0"
Padding="0"> Margin="0,0,5,0"
<Grid ColumnDefinitions="*" RowDefinitions="*,40"> Padding="0">
<ListBox <Grid ColumnDefinitions="*" RowDefinitions="*,40">
ItemsSource="{Binding Items}" <ListBox
Padding="0" Background="#00000000"
Background="#00000000" ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedListItem}"> Padding="0"
<ListBox.ItemTemplate> SelectedItem="{Binding SelectedListItem}">
<DataTemplate DataType="{x:Type models:ListItemTemplate}"> <ListBox.ItemTemplate>
<StackPanel Orientation="Horizontal" Spacing="17"> <DataTemplate DataType="{x:Type models:ListItemTemplate}">
<PathIcon Data="{Binding IconKey, <StackPanel Orientation="Horizontal" Spacing="17">
Converter={x:Static converters:TypeConverters.IconConverter}}" Height="40" Width="40"/> <PathIcon
<TextBlock Text="{Binding Label}" VerticalAlignment="Center"/> Data="{Binding IconKey, Converter={x:Static converters:TypeConverters.IconConverter}}"
</StackPanel> Height="40"
</DataTemplate> Width="40" />
</ListBox.ItemTemplate> <TextBlock Text="{Binding Label}" VerticalAlignment="Center" />
</ListBox> </StackPanel>
<Button Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Stretch" Classes="ViewSelectButton" </DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button
Classes="ViewSelectButton"
Command="{Binding TriggerPaneCommand}"
Grid.Row="1"
HorizontalAlignment="Left"
Padding="15,0,15,0" Padding="15,0,15,0"
Command="{Binding TriggerPaneCommand}"> VerticalAlignment="Stretch">
<Label VerticalAlignment="Center" HorizontalAlignment="Center">|||</Label> <Label HorizontalAlignment="Center" VerticalAlignment="Center">|||</Label>
</Button> </Button>
</Grid> </Grid>
</Border> </Border>
</SplitView.Pane> </SplitView.Pane>
</SplitView> </SplitView>
<Border <Border
Grid.Column="0" BorderThickness="0,2,0,0"
Grid.ColumnSpan="2" CornerRadius="0,0,0,0"
BorderThickness="0,2,0,0" Grid.Column="0"
CornerRadius="0,0,0,0" Grid.ColumnSpan="2"
Grid.Row="1" Grid.Row="1"
Margin="0,0,0,0" Margin="0,0,0,0"
Padding="5"> Padding="5">
<Panel> <Panel>
<Label HorizontalAlignment="Left" VerticalAlignment="Center">cinka.ru</Label> <Label HorizontalAlignment="Left" VerticalAlignment="Center">cinka.ru</Label>
<Label HorizontalAlignment="Right" VerticalAlignment="Center">v0.01</Label> <Label HorizontalAlignment="Right" VerticalAlignment="Center">v0.01</Label>
</Panel> </Panel>
</Border> </Border>
</Grid> </Grid>
<Panel IsVisible="{Binding Popup}">
<Border Background="#111" Opacity="50" />
<Border
CornerRadius="10"
Height="320"
Width="520">
<popup:MessagePopupView />
</Border>
</Panel>
</Panel>
</UserControl> </UserControl>

View File

@@ -0,0 +1,21 @@
<UserControl
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d"
x:Class="Nebula.Launcher.Views.Popup.InfoPopupView"
x:DataType="viewModels:InfoPopupViewModel"
xmlns="https://github.com/avaloniaui"
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>
<viewModels:InfoPopupViewModel />
</Design.DataContext>
<Panel HorizontalAlignment="Center" VerticalAlignment="Center">
<Label>
<TextBlock Text="{Binding InfoText}" />
</Label>
</Panel>
</UserControl>

View File

@@ -0,0 +1,19 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Nebula.Launcher.ViewModels;
namespace Nebula.Launcher.Views.Popup;
public partial class InfoPopupView : UserControl
{
public InfoPopupView()
{
InitializeComponent();
}
public InfoPopupView(InfoPopupViewModel viewModel) : this()
{
DataContext = viewModel;
}
}

View File

@@ -0,0 +1,53 @@
<UserControl
d:DesignHeight="320"
d:DesignWidth="520"
mc:Ignorable="d"
x:Class="Nebula.Launcher.Views.Popup.MessagePopupView"
x:DataType="viewModels:MessagePopupViewModel"
xmlns="https://github.com/avaloniaui"
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>
<viewModels:MessagePopupViewModel />
</Design.DataContext>
<Grid RowDefinitions="35,*,20">
<Border
BorderThickness="0,0,0,2"
CornerRadius="10,10,0,0"
Grid.Row="0">
<Panel Margin="12,0,12,0" VerticalAlignment="Center">
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Center">
<Label VerticalAlignment="Center">Title</Label>
</StackPanel>
<Button
Content="Close"
HorizontalAlignment="Right"
Padding="15,0,15,0"
VerticalAlignment="Center"
x:Name="CloseButton" />
</Panel>
</Border>
<TransitioningContentControl Content="{Binding CurrentPopup}" Grid.Row="0" />
<Border
BorderThickness="0,2,0,2"
CornerRadius="0,0,10,10"
Grid.Row="2">
<Panel Margin="12,0,12,0" VerticalAlignment="Center">
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Center">
<Label
FontSize="8"
Foreground="#666666"
VerticalAlignment="Center">
Дальше бога нет...
</Label>
</StackPanel>
</Panel>
</Border>
</Grid>
</UserControl>

View File

@@ -0,0 +1,26 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Nebula.Launcher.ViewModels;
namespace Nebula.Launcher.Views.Popup;
public partial class MessagePopupView : UserControl
{
// This constructor is used when the view is created by the XAML Previewer
public MessagePopupView()
{
InitializeComponent();
}
// This constructor is used when the view is created via dependency injection
public MessagePopupView(MessagePopupViewModel viewModel)
: this()
{
DataContext = viewModel;
Console.WriteLine("NO SOSAL");
CloseButton.KeyDown += (_,_) => Console.WriteLine("GGG11");
CloseButton.Click += (_,_) => Console.WriteLine("GGG");
}
}