Live.Avalonia integration
Some checks failed
Dotnet build and test / build (push) Failing after 8m25s
Some checks failed
Dotnet build and test / build (push) Failing after 8m25s
This commit is contained in:
parent
eacc4697c9
commit
68b224323b
15 changed files with 321 additions and 10 deletions
|
|
@ -17,12 +17,14 @@
|
|||
<PackageVersion Include="Avalonia.Headless.Xunit" Version="$(AvaloniaVersionBase)" />
|
||||
<PackageVersion Include="Avalonia.Fonts.Inter" Version="$(AvaloniaVersionBase)" />
|
||||
<PackageVersion Include="LibVLCSharp.Avalonia" Version="3.10.1" />
|
||||
<PackageVersion Include="Live.Avalonia" Version="1.4.1" />
|
||||
<PackageVersion Include="Mapsui" Version="5.1.0" />
|
||||
<PackageVersion Include="Mapsui.Avalonia12" Version="5.1.0" />
|
||||
<PackageVersion Include="MarkdownViewer.Core" Version="1.0.5" />
|
||||
<PackageVersion Include="Material.Avalonia" Version="3.20.0" />
|
||||
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.3" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.2" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.12" />
|
||||
<PackageVersion Include="Mono.Options" Version="6.12.0.148" />
|
||||
<PackageVersion Include="PvRecorder" Version="1.2.13" />
|
||||
<PackageVersion Include="Silk.NET.OpenAL" Version="2.23.0" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<application android:label="PostIt" android:icon="@drawable/Icon">
|
||||
<application
|
||||
android:label="PostIt"
|
||||
android:icon="@drawable/Icon"
|
||||
android:networkSecurityConfig="@xml/network_security_config">
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">10.0.2.2</domain> <!-- Debug address -->
|
||||
</domain-config>
|
||||
</network-security-config>
|
||||
|
|
@ -12,10 +12,14 @@ using PostIt.ViewModels;
|
|||
using PostIt.Views;
|
||||
using PostIt.Helpers;
|
||||
using System.Globalization;
|
||||
using Live.Avalonia;
|
||||
using System.Diagnostics;
|
||||
using ReactiveUI;
|
||||
using System.Reactive;
|
||||
|
||||
namespace PostIt;
|
||||
|
||||
public partial class App : Application
|
||||
public partial class App : Application, ILiveView
|
||||
{
|
||||
private int _bootStarted;
|
||||
public string? CliConfigFileSpecification { get; private set; }
|
||||
|
|
@ -38,13 +42,29 @@ public partial class App : Application
|
|||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
|
||||
#if DEBUG
|
||||
this.AttachDeveloperTools();
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
|
||||
#if DEBUG
|
||||
if (Debugger.IsAttached && !IsProduction())
|
||||
{
|
||||
// Debugging requires pdb loading etc, so we disable live reloading
|
||||
// during a test run with an attached debugger.
|
||||
var window = new Window();
|
||||
window.Content = CreateView(window);
|
||||
window.Show();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (TryHandOffCustomSchemeUrl()) return;
|
||||
|
||||
this.ServiceProvider = new ServiceCollection().BuildServices();
|
||||
this.ServiceProvider = new ServiceCollection().BuildPostItServices();
|
||||
var settings = ServiceProvider.GetRequiredService<Settings>();
|
||||
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
|
|
@ -60,9 +80,30 @@ public partial class App : Application
|
|||
InitializeSingleViewLifetime(settings, singleViewPlatform);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
// Here we subscribe to ReactiveUI default exception handler to avoid app
|
||||
// termination in case if we do something wrong in our view models. See:
|
||||
// https://www.reactiveui.net/docs/handbook/default-exception-handler/
|
||||
//
|
||||
// In case if you are using another MV* framework, please refer to its
|
||||
// documentation explaining global exception handling.
|
||||
RxApp.DefaultExceptionHandler = Observer.Create<Exception>(Console.WriteLine);
|
||||
#endif
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
|
||||
private bool IsProduction()
|
||||
{
|
||||
#if DEBUG
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void InitializeSingleViewLifetime(Settings settings, ISingleViewApplicationLifetime singleViewPlatform)
|
||||
{
|
||||
singleViewPlatform.MainView = View = ServiceProvider!.GetRequiredService<MainView>();
|
||||
|
|
@ -213,4 +254,22 @@ public partial class App : Application
|
|||
{
|
||||
this.CliConfigFileSpecification = configFile;
|
||||
}
|
||||
|
||||
public object CreateView(Window window)
|
||||
{
|
||||
if (this.ServiceProvider==null)
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
this.ServiceProvider = serviceCollection.BuildPostItServices();
|
||||
}
|
||||
if (window.DataContext == null)
|
||||
window.DataContext = ServiceProvider!.GetRequiredService<HomePageViewModel>();
|
||||
|
||||
// The AppView class will inherit the DataContext
|
||||
// of the window. The AppView class can be a
|
||||
// UserControl, a Grid, a TextBlock, whatever.
|
||||
this.View = ServiceProvider!.GetRequiredService<MainView>();
|
||||
this.ConfigureRootView(this.View);
|
||||
return this.View;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@ using System;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using PostIt.Services;
|
||||
using PostIt.ViewModels;
|
||||
using PostIt.ViewModels.Chat;
|
||||
using PostIt.Views;
|
||||
using PostIt.Views.Blogs;
|
||||
using PostIt.Views.Chat;
|
||||
using PostIt.Views.Commands;
|
||||
using Yavsc.Api.Client;
|
||||
|
||||
|
|
@ -11,7 +13,7 @@ namespace PostIt.Helpers;
|
|||
|
||||
public static class ServiceCollectionHelpers
|
||||
{
|
||||
public static IServiceProvider BuildServices(this ServiceCollection services)
|
||||
public static IServiceProvider BuildPostItServices(this ServiceCollection services)
|
||||
{
|
||||
var settings = new Settings();
|
||||
settings.Load();
|
||||
|
|
@ -40,6 +42,7 @@ public static class ServiceCollectionHelpers
|
|||
services.AddSingleton<MainView>();
|
||||
services.AddSingleton<BlogsPage>();
|
||||
services.AddSingleton<MainWindow>();
|
||||
services.AddSingleton<ChatViewModel>();
|
||||
|
||||
// SettingsPage is a singleton: there must be one and only one
|
||||
// instance of the settings UI for the lifetime of the app.
|
||||
|
|
@ -59,6 +62,7 @@ public static class ServiceCollectionHelpers
|
|||
services.AddSingleton<CirclesPage>();
|
||||
services.AddSingleton<ActivitiesPage>();
|
||||
services.AddTransient<CommandFormsPage>();
|
||||
services.AddTransient<ChatPage>();
|
||||
services.AddTransient<RdvPage>();
|
||||
services.AddTransient<BrushPage>();
|
||||
services.AddTransient<BillingQueriesPage>();
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public sealed class StatusNotice
|
|||
public string BorderBrush { get; }
|
||||
public string Foreground { get; }
|
||||
|
||||
private StatusNotice(string message, StatusSeverity severity)
|
||||
public StatusNotice(string message, StatusSeverity severity)
|
||||
{
|
||||
Message = string.IsNullOrWhiteSpace(message) ? "Pret." : message;
|
||||
Severity = severity;
|
||||
|
|
@ -33,11 +33,13 @@
|
|||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="LibVLCSharp.Avalonia" />
|
||||
<PackageReference Include="Live.Avalonia" />
|
||||
<PackageReference Include="Mapsui" />
|
||||
<PackageReference Include="Mapsui.Avalonia12" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||
<PackageReference Include="IdentityModel.OidcClient" />
|
||||
<PackageReference Include="MarkdownViewer.Core" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
<PackageReference Include="Mono.Options" />
|
||||
<PackageReference Include="PvRecorder" />
|
||||
|
|
@ -60,5 +62,6 @@
|
|||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Lang/Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Watch Include="**\*.xaml" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@ using Avalonia.Controls.Templates;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using PostIt.ViewModels;
|
||||
using PostIt.ViewModels.Commands;
|
||||
using PostIt.ViewModels.Chat;
|
||||
using PostIt.Views;
|
||||
using PostIt.Views.Blogs;
|
||||
using PostIt.Views.Chat;
|
||||
using PostIt.Views.Commands;
|
||||
|
||||
namespace PostIt;
|
||||
|
|
@ -58,6 +60,7 @@ public class ViewLocator : IDataTemplate
|
|||
EstimateListPageViewModel => services.GetRequiredService<EstimateListPage>(),
|
||||
EstimateValidationPageViewModel => services.GetRequiredService<EstimateValidationPage>(),
|
||||
MyFilesViewModel => services.GetRequiredService<MyFilesPage>(),
|
||||
ChatViewModel => services.GetRequiredService<ChatPage>(),
|
||||
null => new TextBlock { Text = "No view for <null>" },
|
||||
_ => new TextBlock { Text = $"No view for {data.GetType().Name}" }
|
||||
};
|
||||
|
|
|
|||
11
src/PostIt/PostIt/ViewModels/Chat/ChatRoomInfo.cs
Normal file
11
src/PostIt/PostIt/ViewModels/Chat/ChatRoomInfo.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PostIt.ViewModels.Chat
|
||||
{
|
||||
// DTO minimal calqué sur votre logique serveur ChatRoomInfo
|
||||
public class ChatRoomInfo
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
public List<string> Users { get; set; } = new();
|
||||
}
|
||||
}
|
||||
135
src/PostIt/PostIt/ViewModels/Chat/ChatViewModel.cs
Normal file
135
src/PostIt/PostIt/ViewModels/Chat/ChatViewModel.cs
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
|
||||
namespace PostIt.ViewModels.Chat
|
||||
{
|
||||
|
||||
public partial class ChatViewModel : ViewModelBase
|
||||
{
|
||||
private HubConnection? _connection;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string ServerUrl { get; protected set; } = "http://localhost:5000/chathub";
|
||||
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string CurrentRoom { get; set; } = "General";
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string NickName { get; set; } = "";
|
||||
|
||||
[ObservableProperty]
|
||||
public partial StatusNotice Status { get; set; }
|
||||
= new StatusNotice("Déconnecté", StatusSeverity.Info);
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsConnected { get; set; } = false;
|
||||
|
||||
// Listes dynamiques pour l'UI
|
||||
public ObservableCollection<string> Messages { get; } = new();
|
||||
public ObservableCollection<string> ConnectedUsers { get; } = new();
|
||||
|
||||
// Commandes pour les boutons
|
||||
[RelayCommand]
|
||||
public async Task ConnectCommand() => await ConnectAsync();
|
||||
|
||||
[RelayCommand]
|
||||
public async Task JoinRoomCommand() => await JoinRoomAsync();
|
||||
|
||||
[RelayCommand]
|
||||
public async Task ChangeNickCommand() => await ChangeNickAsync();
|
||||
|
||||
public override bool CanNavigateNext { get; protected set; } = false;
|
||||
public override bool CanNavigatePrevious { get; protected set; } = true;
|
||||
|
||||
private async Task ConnectAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
Status = new StatusNotice("Connexion en cours...", StatusSeverity.Info);
|
||||
|
||||
_connection = new HubConnectionBuilder()
|
||||
.WithUrl(ServerUrl)
|
||||
.WithAutomaticReconnect()
|
||||
.Build();
|
||||
|
||||
// 1. Ecoute des notifications globales (notifyUser)
|
||||
_connection.On<string, string, string>("notifyUser", (type, user, msg) =>
|
||||
{
|
||||
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||
Messages.Add($"[{type}] {user}: {msg}"));
|
||||
});
|
||||
|
||||
// 2. Ecoute des notifications de salon (notifyRoom)
|
||||
_connection.On<string, string, string>("notifyRoom", (type, room, user) =>
|
||||
{
|
||||
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
Messages.Add($"*{user} a interagi avec le salon {room} (Action: {type})");
|
||||
if (type == "UserJoin" && !ConnectedUsers.Contains(user))
|
||||
ConnectedUsers.Add(user);
|
||||
});
|
||||
});
|
||||
|
||||
// 3. Réception de l'état complet suite au Join réussi (joint)
|
||||
_connection.On<ChatRoomInfo>("joint", (roomInfo) =>
|
||||
{
|
||||
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
Messages.Add($"Salon rejoint avec succès : {roomInfo.Name}");
|
||||
ConnectedUsers.Clear();
|
||||
foreach (var u in roomInfo.Users) ConnectedUsers.Add(u);
|
||||
});
|
||||
});
|
||||
|
||||
await _connection.StartAsync();
|
||||
IsConnected = true;
|
||||
Status = new StatusNotice("Connecté au Hub SignalR", StatusSeverity.Info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Status = new StatusNotice($"Erreur : {ex.Message}", StatusSeverity.Error);
|
||||
IsConnected = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task JoinRoomAsync()
|
||||
{
|
||||
if (_connection == null || string.IsNullOrWhiteSpace(CurrentRoom)) return;
|
||||
|
||||
try
|
||||
{
|
||||
// Appel de la méthode publique 'Join' du Hub (renvoie un ChatRoomInfo)
|
||||
var info = await _connection.InvokeAsync<ChatRoomInfo>("Join", CurrentRoom);
|
||||
if (info == null)
|
||||
{
|
||||
Messages.Add("Erreur lors de la validation du salon par le serveur.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Messages.Add($"Erreur Join: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ChangeNickAsync()
|
||||
{
|
||||
if (_connection == null || string.IsNullOrWhiteSpace(NickName)) return;
|
||||
|
||||
try
|
||||
{
|
||||
// Appel de la méthode publique 'Nick' du Hub (void)
|
||||
await _connection.InvokeAsync("Nick", NickName);
|
||||
Messages.Add($"Demande de changement de pseudo vers '{NickName}' envoyée.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Messages.Add($"Erreur Nick: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ using CommunityToolkit.Mvvm.Input;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using PostIt.Helpers;
|
||||
using PostIt.Services;
|
||||
using PostIt.ViewModels.Chat;
|
||||
using Yavsc.Api.Client;
|
||||
namespace PostIt.ViewModels;
|
||||
|
||||
|
|
@ -36,7 +37,11 @@ public class HomePageViewModel : ViewModelBase
|
|||
OpenProviderEstimates = new AsyncRelayCommand(() => OpenEstimateListAsync(EstimateListPerspective.Provider));
|
||||
OpenBlogs = new AsyncRelayCommand(App.PushBlogsPageAsync);
|
||||
OpenMyFiles = new AsyncRelayCommand(OpenMyFilesAsync);
|
||||
OpenChat = new AsyncRelayCommand(OpenChatAsync);
|
||||
}
|
||||
|
||||
|
||||
public IAsyncRelayCommand OpenChat { get; }
|
||||
public IAsyncRelayCommand OpenBlogs { get; }
|
||||
public IAsyncRelayCommand OpenActivities { get; }
|
||||
public IAsyncRelayCommand OpenProviderRequests { get; }
|
||||
|
|
@ -103,6 +108,14 @@ public class HomePageViewModel : ViewModelBase
|
|||
await app.PushPageAsync(vm);
|
||||
}
|
||||
|
||||
private async Task OpenChatAsync()
|
||||
{
|
||||
var app = (App?)Application.Current;
|
||||
var vm = app!.ServiceProvider?.GetRequiredService<ChatViewModel>();
|
||||
await app.PushPageAsync(vm!);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ouvre la page « Mes fichiers » (espace de stockage personnel),
|
||||
/// servie par le host Blogs via <c>api/v1/fs</c>.
|
||||
|
|
|
|||
|
|
@ -5,15 +5,12 @@ using Avalonia.Platform.Storage;
|
|||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Controls.Platform;
|
||||
using Avalonia.Input;
|
||||
using System;
|
||||
using Avalonia;
|
||||
|
||||
namespace PostIt.Views.Blogs;
|
||||
|
||||
public partial class BlogsPage : ContentPage
|
||||
{
|
||||
private IInputPane _inputPane;
|
||||
private IInputPane? _inputPane;
|
||||
|
||||
public BlogsPage()
|
||||
{
|
||||
|
|
@ -28,7 +25,7 @@ public partial class BlogsPage : ContentPage
|
|||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel != null)
|
||||
{
|
||||
_inputPane = topLevel.InputPane;
|
||||
_inputPane = topLevel!.InputPane;
|
||||
if (_inputPane != null)
|
||||
{
|
||||
// S'abonne aux changements d'état du clavier virtuel
|
||||
|
|
|
|||
60
src/PostIt/PostIt/Views/Chat/ChatPage..axaml
Normal file
60
src/PostIt/PostIt/Views/Chat/ChatPage..axaml
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
<ContentPage
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:AvaloniaEdit="clr-namespace:AvaloniaEdit;assembly=AvaloniaEdit"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:md="using:MarkdownViewer.Core.Controls"
|
||||
xmlns:models="using:Yavsc.Blogspot"
|
||||
xmlns:postitControls="using:PostIt.Controls"
|
||||
xmlns:views="using:PostIt.Views.Chat"
|
||||
xmlns:vm="using:PostIt.ViewModels.Chat"
|
||||
x:Class="PostIt.Views.Chat.ChatPage"
|
||||
x:DataType="vm:ChatViewModel" >
|
||||
|
||||
<Grid RowDefinitions="Auto, *, Auto" Margin="10">
|
||||
|
||||
<!-- SECTION 1 : BARRE DE CONNEXION & PSEUDO -->
|
||||
<Border Grid.Row="0" Background="#F5F5F5" CornerRadius="5" Padding="10" Margin="0,0,0,10">
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<TextBox Text="{Binding ServerUrl}" Watermark="URL du Hub SignalR" Width="250" VerticalAlignment="Center"/>
|
||||
<Button Content="Connexion" Command="{Binding ConnectCommand}" IsEnabled="{Binding !IsConnected}"/>
|
||||
|
||||
<Separator Background="Gray" Width="1" Margin="5,0"/>
|
||||
|
||||
<TextBox Text="{Binding NickName}" Watermark="Nouveau Pseudo" Width="150" VerticalAlignment="Center"/>
|
||||
<Button Content="Changer Nick" Command="{Binding ChangeNickCommand}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- SECTION 2 : ESPACE CENTRAL DU CHAT -->
|
||||
<Grid Grid.Row="1" ColumnDefinitions="*, 200" Margin="0,0,0,10">
|
||||
|
||||
<!-- Journal des flux de messages & notifications -->
|
||||
<Grid Grid.Column="0" RowDefinitions="Auto, *">
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal" Spacing="10" Margin="0,0,0,5">
|
||||
<TextBox Text="{Binding CurrentRoom}" Watermark="Nom du salon" Width="200" VerticalAlignment="Center"/>
|
||||
<Button Content="Rejoindre Salon (Join)" Command="{Binding JoinRoomCommand}"/>
|
||||
</StackPanel>
|
||||
|
||||
<ListBox Grid.Row="1" ItemsSource="{Binding Messages}" Background="#FAFAFA" BorderBrush="#E0E0E0" BorderThickness="1">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding}" TextWrapping="Wrap"/>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
|
||||
<!-- Liste des utilisateurs présents (MàJ via l'événement 'joint') -->
|
||||
<Border Grid.Column="1" Margin="10,0,0,0" BorderBrush="#E0E0E0" BorderThickness="1" Background="#FFF">
|
||||
<Grid RowDefinitions="Auto, *">
|
||||
<TextBlock Grid.Row="0" Text="Membres Présents" FontWeight="Bold" Margin="5" HorizontalAlignment="Center"/>
|
||||
<ListBox Grid.Row="1" ItemsSource="{Binding ConnectedUsers}" BorderThickness="0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
<postitControls:StatusBar Grid.Row="4" DataContext="{Binding Status+ "Raaaahhh!"}" x:Name="StatusBar" />
|
||||
|
||||
</Grid>
|
||||
</ContentPage>
|
||||
10
src/PostIt/PostIt/Views/Chat/ChatPage.axaml.cs
Normal file
10
src/PostIt/PostIt/Views/Chat/ChatPage.axaml.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
using Avalonia.Controls;
|
||||
namespace PostIt.Views.Chat;
|
||||
public partial class ChatPage : ContentPage
|
||||
{
|
||||
|
||||
public ChatPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,11 @@
|
|||
FontSize="22"
|
||||
FontWeight="SemiBold"
|
||||
HorizontalAlignment="Center"/>
|
||||
|
||||
<Button Content="Chat"
|
||||
Command="{Binding OpenChat}"
|
||||
HorizontalAlignment="Center"
|
||||
IsEnabled="{Binding SessionStatus.IsLoggedIn}"/>
|
||||
<Button Content="Open Blog Interface"
|
||||
Command="{Binding OpenBlogs}"
|
||||
HorizontalAlignment="Center"
|
||||
|
|
|
|||
Loading…
Reference in a new issue