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.Headless.Xunit" Version="$(AvaloniaVersionBase)" />
|
||||||
<PackageVersion Include="Avalonia.Fonts.Inter" Version="$(AvaloniaVersionBase)" />
|
<PackageVersion Include="Avalonia.Fonts.Inter" Version="$(AvaloniaVersionBase)" />
|
||||||
<PackageVersion Include="LibVLCSharp.Avalonia" Version="3.10.1" />
|
<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" Version="5.1.0" />
|
||||||
<PackageVersion Include="Mapsui.Avalonia12" Version="5.1.0" />
|
<PackageVersion Include="Mapsui.Avalonia12" Version="5.1.0" />
|
||||||
<PackageVersion Include="MarkdownViewer.Core" Version="1.0.5" />
|
<PackageVersion Include="MarkdownViewer.Core" Version="1.0.5" />
|
||||||
<PackageVersion Include="Material.Avalonia" Version="3.20.0" />
|
<PackageVersion Include="Material.Avalonia" Version="3.20.0" />
|
||||||
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.3" />
|
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.3" />
|
||||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.2" />
|
<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="Mono.Options" Version="6.12.0.148" />
|
||||||
<PackageVersion Include="PvRecorder" Version="1.2.13" />
|
<PackageVersion Include="PvRecorder" Version="1.2.13" />
|
||||||
<PackageVersion Include="Silk.NET.OpenAL" Version="2.23.0" />
|
<PackageVersion Include="Silk.NET.OpenAL" Version="2.23.0" />
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto">
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<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>
|
</application>
|
||||||
</manifest>
|
</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.Views;
|
||||||
using PostIt.Helpers;
|
using PostIt.Helpers;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using Live.Avalonia;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using ReactiveUI;
|
||||||
|
using System.Reactive;
|
||||||
|
|
||||||
namespace PostIt;
|
namespace PostIt;
|
||||||
|
|
||||||
public partial class App : Application
|
public partial class App : Application, ILiveView
|
||||||
{
|
{
|
||||||
private int _bootStarted;
|
private int _bootStarted;
|
||||||
public string? CliConfigFileSpecification { get; private set; }
|
public string? CliConfigFileSpecification { get; private set; }
|
||||||
|
|
@ -38,13 +42,29 @@ public partial class App : Application
|
||||||
{
|
{
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
this.AttachDeveloperTools();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnFrameworkInitializationCompleted()
|
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;
|
if (TryHandOffCustomSchemeUrl()) return;
|
||||||
|
|
||||||
this.ServiceProvider = new ServiceCollection().BuildServices();
|
this.ServiceProvider = new ServiceCollection().BuildPostItServices();
|
||||||
var settings = ServiceProvider.GetRequiredService<Settings>();
|
var settings = ServiceProvider.GetRequiredService<Settings>();
|
||||||
|
|
||||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||||
|
|
@ -60,9 +80,30 @@ public partial class App : Application
|
||||||
InitializeSingleViewLifetime(settings, singleViewPlatform);
|
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();
|
base.OnFrameworkInitializationCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsProduction()
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
public void InitializeSingleViewLifetime(Settings settings, ISingleViewApplicationLifetime singleViewPlatform)
|
public void InitializeSingleViewLifetime(Settings settings, ISingleViewApplicationLifetime singleViewPlatform)
|
||||||
{
|
{
|
||||||
singleViewPlatform.MainView = View = ServiceProvider!.GetRequiredService<MainView>();
|
singleViewPlatform.MainView = View = ServiceProvider!.GetRequiredService<MainView>();
|
||||||
|
|
@ -213,4 +254,22 @@ public partial class App : Application
|
||||||
{
|
{
|
||||||
this.CliConfigFileSpecification = configFile;
|
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 Microsoft.Extensions.DependencyInjection;
|
||||||
using PostIt.Services;
|
using PostIt.Services;
|
||||||
using PostIt.ViewModels;
|
using PostIt.ViewModels;
|
||||||
|
using PostIt.ViewModels.Chat;
|
||||||
using PostIt.Views;
|
using PostIt.Views;
|
||||||
using PostIt.Views.Blogs;
|
using PostIt.Views.Blogs;
|
||||||
|
using PostIt.Views.Chat;
|
||||||
using PostIt.Views.Commands;
|
using PostIt.Views.Commands;
|
||||||
using Yavsc.Api.Client;
|
using Yavsc.Api.Client;
|
||||||
|
|
||||||
|
|
@ -11,7 +13,7 @@ namespace PostIt.Helpers;
|
||||||
|
|
||||||
public static class ServiceCollectionHelpers
|
public static class ServiceCollectionHelpers
|
||||||
{
|
{
|
||||||
public static IServiceProvider BuildServices(this ServiceCollection services)
|
public static IServiceProvider BuildPostItServices(this ServiceCollection services)
|
||||||
{
|
{
|
||||||
var settings = new Settings();
|
var settings = new Settings();
|
||||||
settings.Load();
|
settings.Load();
|
||||||
|
|
@ -40,6 +42,7 @@ public static class ServiceCollectionHelpers
|
||||||
services.AddSingleton<MainView>();
|
services.AddSingleton<MainView>();
|
||||||
services.AddSingleton<BlogsPage>();
|
services.AddSingleton<BlogsPage>();
|
||||||
services.AddSingleton<MainWindow>();
|
services.AddSingleton<MainWindow>();
|
||||||
|
services.AddSingleton<ChatViewModel>();
|
||||||
|
|
||||||
// SettingsPage is a singleton: there must be one and only one
|
// SettingsPage is a singleton: there must be one and only one
|
||||||
// instance of the settings UI for the lifetime of the app.
|
// instance of the settings UI for the lifetime of the app.
|
||||||
|
|
@ -59,6 +62,7 @@ public static class ServiceCollectionHelpers
|
||||||
services.AddSingleton<CirclesPage>();
|
services.AddSingleton<CirclesPage>();
|
||||||
services.AddSingleton<ActivitiesPage>();
|
services.AddSingleton<ActivitiesPage>();
|
||||||
services.AddTransient<CommandFormsPage>();
|
services.AddTransient<CommandFormsPage>();
|
||||||
|
services.AddTransient<ChatPage>();
|
||||||
services.AddTransient<RdvPage>();
|
services.AddTransient<RdvPage>();
|
||||||
services.AddTransient<BrushPage>();
|
services.AddTransient<BrushPage>();
|
||||||
services.AddTransient<BillingQueriesPage>();
|
services.AddTransient<BillingQueriesPage>();
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ public sealed class StatusNotice
|
||||||
public string BorderBrush { get; }
|
public string BorderBrush { get; }
|
||||||
public string Foreground { get; }
|
public string Foreground { get; }
|
||||||
|
|
||||||
private StatusNotice(string message, StatusSeverity severity)
|
public StatusNotice(string message, StatusSeverity severity)
|
||||||
{
|
{
|
||||||
Message = string.IsNullOrWhiteSpace(message) ? "Pret." : message;
|
Message = string.IsNullOrWhiteSpace(message) ? "Pret." : message;
|
||||||
Severity = severity;
|
Severity = severity;
|
||||||
|
|
@ -33,11 +33,13 @@
|
||||||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="LibVLCSharp.Avalonia" />
|
<PackageReference Include="LibVLCSharp.Avalonia" />
|
||||||
|
<PackageReference Include="Live.Avalonia" />
|
||||||
<PackageReference Include="Mapsui" />
|
<PackageReference Include="Mapsui" />
|
||||||
<PackageReference Include="Mapsui.Avalonia12" />
|
<PackageReference Include="Mapsui.Avalonia12" />
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" />
|
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||||
<PackageReference Include="IdentityModel.OidcClient" />
|
<PackageReference Include="IdentityModel.OidcClient" />
|
||||||
<PackageReference Include="MarkdownViewer.Core" />
|
<PackageReference Include="MarkdownViewer.Core" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||||
<PackageReference Include="Mono.Options" />
|
<PackageReference Include="Mono.Options" />
|
||||||
<PackageReference Include="PvRecorder" />
|
<PackageReference Include="PvRecorder" />
|
||||||
|
|
@ -60,5 +62,6 @@
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
<DependentUpon>Lang/Resources.resx</DependentUpon>
|
<DependentUpon>Lang/Resources.resx</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Watch Include="**\*.xaml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,10 @@ using Avalonia.Controls.Templates;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using PostIt.ViewModels;
|
using PostIt.ViewModels;
|
||||||
using PostIt.ViewModels.Commands;
|
using PostIt.ViewModels.Commands;
|
||||||
|
using PostIt.ViewModels.Chat;
|
||||||
using PostIt.Views;
|
using PostIt.Views;
|
||||||
using PostIt.Views.Blogs;
|
using PostIt.Views.Blogs;
|
||||||
|
using PostIt.Views.Chat;
|
||||||
using PostIt.Views.Commands;
|
using PostIt.Views.Commands;
|
||||||
|
|
||||||
namespace PostIt;
|
namespace PostIt;
|
||||||
|
|
@ -58,6 +60,7 @@ public class ViewLocator : IDataTemplate
|
||||||
EstimateListPageViewModel => services.GetRequiredService<EstimateListPage>(),
|
EstimateListPageViewModel => services.GetRequiredService<EstimateListPage>(),
|
||||||
EstimateValidationPageViewModel => services.GetRequiredService<EstimateValidationPage>(),
|
EstimateValidationPageViewModel => services.GetRequiredService<EstimateValidationPage>(),
|
||||||
MyFilesViewModel => services.GetRequiredService<MyFilesPage>(),
|
MyFilesViewModel => services.GetRequiredService<MyFilesPage>(),
|
||||||
|
ChatViewModel => services.GetRequiredService<ChatPage>(),
|
||||||
null => new TextBlock { Text = "No view for <null>" },
|
null => new TextBlock { Text = "No view for <null>" },
|
||||||
_ => new TextBlock { Text = $"No view for {data.GetType().Name}" }
|
_ => 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 Microsoft.Extensions.DependencyInjection;
|
||||||
using PostIt.Helpers;
|
using PostIt.Helpers;
|
||||||
using PostIt.Services;
|
using PostIt.Services;
|
||||||
|
using PostIt.ViewModels.Chat;
|
||||||
using Yavsc.Api.Client;
|
using Yavsc.Api.Client;
|
||||||
namespace PostIt.ViewModels;
|
namespace PostIt.ViewModels;
|
||||||
|
|
||||||
|
|
@ -36,7 +37,11 @@ public class HomePageViewModel : ViewModelBase
|
||||||
OpenProviderEstimates = new AsyncRelayCommand(() => OpenEstimateListAsync(EstimateListPerspective.Provider));
|
OpenProviderEstimates = new AsyncRelayCommand(() => OpenEstimateListAsync(EstimateListPerspective.Provider));
|
||||||
OpenBlogs = new AsyncRelayCommand(App.PushBlogsPageAsync);
|
OpenBlogs = new AsyncRelayCommand(App.PushBlogsPageAsync);
|
||||||
OpenMyFiles = new AsyncRelayCommand(OpenMyFilesAsync);
|
OpenMyFiles = new AsyncRelayCommand(OpenMyFilesAsync);
|
||||||
|
OpenChat = new AsyncRelayCommand(OpenChatAsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IAsyncRelayCommand OpenChat { get; }
|
||||||
public IAsyncRelayCommand OpenBlogs { get; }
|
public IAsyncRelayCommand OpenBlogs { get; }
|
||||||
public IAsyncRelayCommand OpenActivities { get; }
|
public IAsyncRelayCommand OpenActivities { get; }
|
||||||
public IAsyncRelayCommand OpenProviderRequests { get; }
|
public IAsyncRelayCommand OpenProviderRequests { get; }
|
||||||
|
|
@ -103,6 +108,14 @@ public class HomePageViewModel : ViewModelBase
|
||||||
await app.PushPageAsync(vm);
|
await app.PushPageAsync(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task OpenChatAsync()
|
||||||
|
{
|
||||||
|
var app = (App?)Application.Current;
|
||||||
|
var vm = app!.ServiceProvider?.GetRequiredService<ChatViewModel>();
|
||||||
|
await app.PushPageAsync(vm!);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ouvre la page « Mes fichiers » (espace de stockage personnel),
|
/// Ouvre la page « Mes fichiers » (espace de stockage personnel),
|
||||||
/// servie par le host Blogs via <c>api/v1/fs</c>.
|
/// 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.Controls.Primitives;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Controls.Platform;
|
using Avalonia.Controls.Platform;
|
||||||
using Avalonia.Input;
|
|
||||||
using System;
|
|
||||||
using Avalonia;
|
|
||||||
|
|
||||||
namespace PostIt.Views.Blogs;
|
namespace PostIt.Views.Blogs;
|
||||||
|
|
||||||
public partial class BlogsPage : ContentPage
|
public partial class BlogsPage : ContentPage
|
||||||
{
|
{
|
||||||
private IInputPane _inputPane;
|
private IInputPane? _inputPane;
|
||||||
|
|
||||||
public BlogsPage()
|
public BlogsPage()
|
||||||
{
|
{
|
||||||
|
|
@ -28,7 +25,7 @@ public partial class BlogsPage : ContentPage
|
||||||
var topLevel = TopLevel.GetTopLevel(this);
|
var topLevel = TopLevel.GetTopLevel(this);
|
||||||
if (topLevel != null)
|
if (topLevel != null)
|
||||||
{
|
{
|
||||||
_inputPane = topLevel.InputPane;
|
_inputPane = topLevel!.InputPane;
|
||||||
if (_inputPane != null)
|
if (_inputPane != null)
|
||||||
{
|
{
|
||||||
// S'abonne aux changements d'état du clavier virtuel
|
// 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"
|
FontSize="22"
|
||||||
FontWeight="SemiBold"
|
FontWeight="SemiBold"
|
||||||
HorizontalAlignment="Center"/>
|
HorizontalAlignment="Center"/>
|
||||||
|
|
||||||
|
<Button Content="Chat"
|
||||||
|
Command="{Binding OpenChat}"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
IsEnabled="{Binding SessionStatus.IsLoggedIn}"/>
|
||||||
<Button Content="Open Blog Interface"
|
<Button Content="Open Blog Interface"
|
||||||
Command="{Binding OpenBlogs}"
|
Command="{Binding OpenBlogs}"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue