Initial scaffolding: PS_Launcher v0.2
Client (C# / .NET 8 / WPF, MVVM via CommunityToolkit.Mvvm):
- PSLauncher.App: WPF UI dark theme (Epic-style sidebar + hero + big play button)
with UpdateAvailableDialog rendering Markdown release notes via Markdig.Wpf.
- PSLauncher.Core: services for installation registry (scans Proserve v{X.Y.Z}/),
process launcher, manifest fetch, SHA-256 integrity, HTTP download with
progress, ZIP install via .tmp + atomic rename, update orchestrator.
- PSLauncher.Models: RemoteManifest, InstalledVersion, LocalConfig DTOs.
Server (PHP 8 for OVH mutualisé, deployed under www/PS_Launcher/):
- Front controller + routes /manifest and /releasenotes/{version}.
- Static signed-manifest workflow with tools/sign-manifest.php CLI to
recompute SHA-256 and sizeBytes after each ZIP upload.
- .htaccess: HTTPS redirect, rewrite, security headers.
- config.example.php template; real config.php is gitignored.
Cohabiting versions: each release lives in its own Proserve v{version}/ folder
under installRoot. Old versions are never deleted automatically.
Roadmap: v0.3 = HTTP Range resume + Polly retry + state.json,
v0.4 = MySQL license + Ed25519 signatures + DPAPI, v0.5 = settings/UX polish.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
194
src/PSLauncher.App/Views/MainWindow.xaml
Normal file
194
src/PSLauncher.App/Views/MainWindow.xaml
Normal file
@@ -0,0 +1,194 @@
|
||||
<Window x:Class="PSLauncher.App.Views.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:PSLauncher.App.ViewModels"
|
||||
xmlns:views="clr-namespace:PSLauncher.App.Views"
|
||||
Title="PROSERVE Launcher"
|
||||
Width="1280" Height="800"
|
||||
MinWidth="900" MinHeight="600"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
d:DataContext="{d:DesignInstance Type=vm:MainViewModel}"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" /> <!-- Top bar -->
|
||||
<RowDefinition Height="*" /> <!-- Body -->
|
||||
<RowDefinition Height="Auto" /> <!-- Footer (download) -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Top bar -->
|
||||
<Border Grid.Row="0" Background="{StaticResource Brush.Bg.Sidebar}"
|
||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="0,0,0,1"
|
||||
Padding="20,12">
|
||||
<Grid>
|
||||
<TextBlock Text="PROSERVE" FontSize="18" FontWeight="Bold"
|
||||
Foreground="{StaticResource Brush.Text.Primary}"
|
||||
VerticalAlignment="Center" />
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding LicenseSummary}"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
VerticalAlignment="Center" Margin="0,0,12,0" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Body : sidebar + content -->
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="200" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<Border Grid.Column="0" Background="{StaticResource Brush.Bg.Sidebar}"
|
||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="0,0,1,0">
|
||||
<StackPanel>
|
||||
<RadioButton Style="{StaticResource SidebarItem}" GroupName="Nav"
|
||||
Content="📚 Bibliothèque" IsChecked="True" />
|
||||
<RadioButton Style="{StaticResource SidebarItem}" GroupName="Nav"
|
||||
Content="📰 Nouveautés" IsEnabled="False" />
|
||||
<RadioButton Style="{StaticResource SidebarItem}" GroupName="Nav"
|
||||
Content="⚙️ Paramètres" IsEnabled="False" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Library content -->
|
||||
<ScrollViewer Grid.Column="1" VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="40,30">
|
||||
|
||||
<!-- Hero -->
|
||||
<Border Background="#2A2A30" CornerRadius="8" Height="280"
|
||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1">
|
||||
<Grid>
|
||||
<TextBlock Text="PROSERVE"
|
||||
FontSize="64" FontWeight="Bold"
|
||||
Foreground="#3D3D45"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
<Border VerticalAlignment="Bottom" HorizontalAlignment="Left"
|
||||
Margin="24" Background="#000000B0"
|
||||
CornerRadius="4" Padding="12,6">
|
||||
<TextBlock Text="{Binding HeroTitle}"
|
||||
FontSize="22" FontWeight="SemiBold"
|
||||
Foreground="White" />
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Action row -->
|
||||
<Grid Margin="0,24,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Version selector -->
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<TextBlock Text="Version :" Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
VerticalAlignment="Center" Margin="0,0,10,0" />
|
||||
<ComboBox Width="160"
|
||||
ItemsSource="{Binding InstalledVersions}"
|
||||
DisplayMemberPath="Display"
|
||||
SelectedItem="{Binding SelectedVersion, Mode=TwoWay}" />
|
||||
<Border Style="{StaticResource VersionPill}" Margin="12,0,0,0">
|
||||
<TextBlock Text="{Binding StatusBadge}" FontSize="12"
|
||||
Foreground="{StaticResource Brush.Text.Primary}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Primary action -->
|
||||
<Button Grid.Column="2"
|
||||
Style="{StaticResource PrimaryButton}"
|
||||
Content="{Binding PrimaryActionLabel}"
|
||||
Command="{Binding PrimaryActionCommand}"
|
||||
IsEnabled="{Binding PrimaryActionEnabled}" />
|
||||
</Grid>
|
||||
|
||||
<!-- Secondary actions -->
|
||||
<StackPanel Orientation="Horizontal" Margin="0,16,0,0">
|
||||
<Button Style="{StaticResource SecondaryButton}"
|
||||
Content="🔄 Vérifier les mises à jour"
|
||||
Command="{Binding CheckForUpdatesCommand}"
|
||||
Margin="0,0,10,0" />
|
||||
<Button Style="{StaticResource SecondaryButton}"
|
||||
Content="📁 Ouvrir le dossier"
|
||||
Command="{Binding OpenFolderCommand}"
|
||||
Margin="0,0,10,0" />
|
||||
<Button Style="{StaticResource SecondaryButton}"
|
||||
Content="🔍 Rescanner local"
|
||||
Command="{Binding RefreshCommand}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Installed versions list -->
|
||||
<TextBlock Text="Versions installées" FontSize="16" FontWeight="SemiBold"
|
||||
Margin="0,30,0,12"
|
||||
Foreground="{StaticResource Brush.Text.Primary}" />
|
||||
<ItemsControl ItemsSource="{Binding InstalledVersions}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Background="{StaticResource Brush.Bg.Card}"
|
||||
CornerRadius="6" Margin="0,0,0,8" Padding="16,12"
|
||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Text="{Binding Display}"
|
||||
FontSize="15" FontWeight="SemiBold" />
|
||||
<TextBlock Text="{Binding Subtitle}"
|
||||
FontSize="12"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
Margin="0,2,0,0" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<!-- Empty state -->
|
||||
<TextBlock Text="{Binding EmptyHint}"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
TextWrapping="Wrap" Margin="0,12,0,0"
|
||||
Visibility="{Binding EmptyHintVisibility}" />
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
<!-- Footer (download/install status) -->
|
||||
<Border Grid.Row="2" Background="{StaticResource Brush.Bg.Footer}"
|
||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="0,1,0,0"
|
||||
Padding="20,8"
|
||||
Visibility="{Binding FooterVisibility}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Text="{Binding FooterText}"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}" />
|
||||
<ProgressBar Height="4" Margin="0,4,0,0"
|
||||
Value="{Binding ProgressPercent}"
|
||||
Maximum="100"
|
||||
Foreground="{StaticResource Brush.Accent}"
|
||||
Background="#2A2A30"
|
||||
BorderThickness="0" />
|
||||
</StackPanel>
|
||||
<Button Grid.Column="1"
|
||||
Style="{StaticResource SecondaryButton}"
|
||||
Content="Annuler"
|
||||
VerticalAlignment="Center"
|
||||
Margin="12,0,0,0"
|
||||
Command="{Binding CancelDownloadCommand}"
|
||||
Visibility="{Binding IsBusy, Converter={StaticResource BoolToVisibility}}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Window>
|
||||
Reference in New Issue
Block a user