Restyle the Avalonia server host and add a single-file publish workflow (#18)

Give the host a cohesive vault-terminal look: header wordmark with a live
status pill that glows green while running, sectioned configuration card with
per-field labels, a terminal-style server log, richer player rows (id, name,
address, packet counts), and a bold Start/Stop control bar. All existing
bindings are unchanged.

Add publish-host.yml to build self-contained, single-file win-x64 and
linux-x64 binaries on the self-hosted runner and upload them as artifacts,
and document the untrimmed publish commands in the host README.
This commit is contained in:
Nomads_Reach
2026-08-16 18:47:14 -04:00
committed by GitHub
parent 2f6100907f
commit ea275210cd
4 changed files with 437 additions and 82 deletions
+177 -73
View File
@@ -3,102 +3,206 @@
xmlns:vm="clr-namespace:CommonwealthOnline.Host.ViewModels"
x:Class="CommonwealthOnline.Host.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
Width="960" Height="700"
MinWidth="820" MinHeight="600"
Width="1040" Height="740"
MinWidth="900" MinHeight="640"
Title="Commonwealth Online — Server Host"
Background="{StaticResource CoBackgroundBrush}">
Background="{StaticResource CoWindowBrush}">
<Grid RowDefinitions="Auto,*,Auto" Margin="18">
<Grid RowDefinitions="Auto,*,Auto">
<Image Grid.Row="0" Source="/Assets/logo.png" Height="84"
HorizontalAlignment="Left" Margin="0,0,0,14" />
<!-- ============ Header ============ -->
<Border Grid.Row="0" Background="{StaticResource CoBarBrush}"
BorderBrush="{StaticResource CoBorderBrush}" BorderThickness="0,0,0,1"
Padding="20,12">
<Grid ColumnDefinitions="Auto,*,Auto" VerticalAlignment="Center">
<Grid Grid.Row="1" ColumnDefinitions="330,*">
<StackPanel Grid.Column="0" Orientation="Horizontal" Spacing="14" VerticalAlignment="Center">
<Image Source="/Assets/logo.png" Height="42" VerticalAlignment="Center" />
<StackPanel VerticalAlignment="Center" Spacing="1">
<TextBlock Text="COMMONWEALTH ONLINE" Foreground="{StaticResource CoAccentBrush}"
FontWeight="Bold" FontSize="16" LetterSpacing="3" />
<TextBlock Text="DEDICATED SERVER HOST" Foreground="{StaticResource CoMutedBrush}"
FontSize="10" LetterSpacing="4" />
</StackPanel>
</StackPanel>
<StackPanel Grid.Column="0" Spacing="9" Margin="0,0,18,0">
<TextBlock Text="SERVER" Foreground="{StaticResource CoAccentBrush}"
FontWeight="Bold" FontSize="13" />
<TextBox Watermark="Server name" Text="{Binding ServerName}" />
<Grid ColumnDefinitions="*,*">
<TextBox Grid.Column="0" Watermark="Host" Text="{Binding Host}" Margin="0,0,4,0" />
<TextBox Grid.Column="1" Watermark="Port" Text="{Binding Port}" Margin="4,0,0,0" />
</Grid>
<Grid ColumnDefinitions="*,*">
<TextBox Grid.Column="0" Watermark="Max players" Text="{Binding MaxPlayers}" Margin="0,0,4,0" />
<TextBox Grid.Column="1" Watermark="Admin port" Text="{Binding AdminPort}" Margin="4,0,0,0" />
</Grid>
<TextBlock Text="LOG VERBOSITY" Foreground="{StaticResource CoAccentBrush}"
FontWeight="Bold" FontSize="12" Margin="0,4,0,0" />
<ComboBox HorizontalAlignment="Stretch"
ItemsSource="{Binding VerbosityOptions}"
SelectedItem="{Binding LogVerbosity}" />
<CheckBox Content="Enable GNS transport" IsChecked="{Binding EnableGnsTransport}"
Foreground="{StaticResource CoTextBrush}" />
<Button Content="Save config" Command="{Binding SaveCommand}"
HorizontalAlignment="Stretch" />
</StackPanel>
<!-- Live status pill -->
<Border Grid.Column="2" Classes="pill" Classes.on="{Binding IsRunning}"
Background="{StaticResource CoSurface2Brush}"
BorderThickness="1"
CornerRadius="14" Padding="14,7" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal" Spacing="9" VerticalAlignment="Center">
<Ellipse Classes="dot" Classes.on="{Binding IsRunning}"
Width="10" Height="10" VerticalAlignment="Center" />
<TextBlock Text="{Binding StatusText}" Foreground="{StaticResource CoTextBrush}"
FontWeight="SemiBold" FontSize="13" LetterSpacing="1"
VerticalAlignment="Center" />
</StackPanel>
</Border>
</Grid>
</Border>
<!-- ============ Body ============ -->
<Grid Grid.Row="1" ColumnDefinitions="352,*" Margin="20,18,20,14">
<!-- Config card -->
<Border Grid.Column="0" Classes="card" Background="{StaticResource CoSurfaceBrush}"
BorderBrush="{StaticResource CoBorderBrush}" BorderThickness="1"
CornerRadius="8" Padding="18" Margin="0,0,18,0">
<StackPanel Spacing="12">
<TextBlock Classes="section" Text="CONFIGURATION" />
<StackPanel Spacing="4">
<TextBlock Classes="fieldlabel" Text="SERVER NAME" />
<TextBox Watermark="My Commonwealth server" Text="{Binding ServerName}" />
</StackPanel>
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="4" Margin="0,0,8,0">
<TextBlock Classes="fieldlabel" Text="HOST ADDRESS" />
<TextBox Watermark="0.0.0.0" Text="{Binding Host}" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="4" Width="96">
<TextBlock Classes="fieldlabel" Text="PORT" />
<TextBox Watermark="7777" Text="{Binding Port}" />
</StackPanel>
</Grid>
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="4" Margin="0,0,8,0">
<TextBlock Classes="fieldlabel" Text="MAX PLAYERS" />
<TextBox Watermark="16" Text="{Binding MaxPlayers}" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="4" Width="96">
<TextBlock Classes="fieldlabel" Text="ADMIN PORT" />
<TextBox Watermark="7779" Text="{Binding AdminPort}" />
</StackPanel>
</Grid>
<StackPanel Spacing="4">
<TextBlock Classes="fieldlabel" Text="LOG VERBOSITY" />
<ComboBox HorizontalAlignment="Stretch"
ItemsSource="{Binding VerbosityOptions}"
SelectedItem="{Binding LogVerbosity}" />
</StackPanel>
<Border Background="{StaticResource CoSurface2Brush}"
BorderBrush="{StaticResource CoBorderBrush}" BorderThickness="1"
CornerRadius="5" Padding="10,8" Margin="0,2,0,0">
<CheckBox Content="Enable GNS transport (UDP)"
IsChecked="{Binding EnableGnsTransport}" />
</Border>
<Button Classes="ghost" Content="Save configuration"
Command="{Binding SaveCommand}"
HorizontalAlignment="Stretch" Margin="0,4,0,0" />
</StackPanel>
</Border>
<!-- Right column: log + players -->
<Grid Grid.Column="1" RowDefinitions="*,Auto">
<Border Grid.Row="0" Background="{StaticResource CoSurfaceBrush}"
CornerRadius="4" Padding="10">
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Log}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Foreground="{StaticResource CoTextBrush}"
FontFamily="Cascadia Mono,Consolas,monospace" FontSize="12"
TextWrapping="Wrap" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!-- Server log -->
<Border Grid.Row="0" Classes="card" Background="{StaticResource CoSurfaceBrush}"
BorderBrush="{StaticResource CoBorderBrush}" BorderThickness="1"
CornerRadius="8" Padding="0">
<Grid RowDefinitions="Auto,*">
<Border Grid.Row="0" Background="{StaticResource CoSurface2Brush}"
BorderBrush="{StaticResource CoBorderBrush}" BorderThickness="0,0,0,1"
CornerRadius="8,8,0,0" Padding="14,9">
<StackPanel Orientation="Horizontal" Spacing="9">
<Ellipse Classes="dot" Classes.on="{Binding IsRunning}"
Width="9" Height="9" VerticalAlignment="Center" />
<TextBlock Classes="section" Text="SERVER LOG" VerticalAlignment="Center" />
</StackPanel>
</Border>
<ScrollViewer Grid.Row="1" Padding="14,10" x:Name="LogScroll">
<ItemsControl ItemsSource="{Binding Log}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Foreground="{StaticResource CoTextBrush}"
FontFamily="Cascadia Mono,Consolas,Menlo,monospace" FontSize="12"
TextWrapping="Wrap" Margin="0,0,0,1" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Border>
<Border Grid.Row="1" Background="{StaticResource CoSurfaceBrush}"
CornerRadius="4" Padding="10" Margin="0,10,0,0" Height="188">
<!-- Players -->
<Border Grid.Row="1" Classes="card" Background="{StaticResource CoSurfaceBrush}"
BorderBrush="{StaticResource CoBorderBrush}" BorderThickness="1"
CornerRadius="8" Padding="0" Margin="0,14,0,0" Height="210">
<Grid RowDefinitions="Auto,*,Auto">
<DockPanel Grid.Row="0" Margin="0,0,0,6">
<TextBlock DockPanel.Dock="Left" Text="PLAYERS"
Foreground="{StaticResource CoAccentBrush}" FontWeight="Bold" FontSize="12" />
<TextBlock DockPanel.Dock="Right" Text="{Binding StatsText}"
Foreground="{StaticResource CoTextBrush}" FontSize="11"
HorizontalAlignment="Right" />
</DockPanel>
<ListBox Grid.Row="1" Background="Transparent"
<Border Grid.Row="0" Background="{StaticResource CoSurface2Brush}"
BorderBrush="{StaticResource CoBorderBrush}" BorderThickness="0,0,0,1"
CornerRadius="8,8,0,0" Padding="14,9">
<DockPanel>
<TextBlock DockPanel.Dock="Left" Classes="section" Text="PLAYERS"
VerticalAlignment="Center" />
<TextBlock DockPanel.Dock="Right" Text="{Binding StatsText}"
Foreground="{StaticResource CoMutedBrush}" FontSize="11"
FontFamily="Cascadia Mono,Consolas,monospace"
HorizontalAlignment="Right" VerticalAlignment="Center" />
</DockPanel>
</Border>
<ListBox Grid.Row="1" Margin="6,4"
ItemsSource="{Binding Players}" SelectedItem="{Binding SelectedPlayer}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Display}" Foreground="{StaticResource CoTextBrush}"
FontFamily="Cascadia Mono,Consolas,monospace" FontSize="12" />
<DataTemplate x:DataType="vm:PlayerRow">
<Grid ColumnDefinitions="52,*,Auto" >
<TextBlock Grid.Column="0" Text="{Binding PlayerId, StringFormat='#{0}'}"
Foreground="{StaticResource CoAccentBrush}" FontWeight="Bold"
FontFamily="Cascadia Mono,Consolas,monospace" FontSize="12"
VerticalAlignment="Center" />
<StackPanel Grid.Column="1" VerticalAlignment="Center" Spacing="0">
<TextBlock Text="{Binding Label}" Foreground="{StaticResource CoTextBrush}"
FontSize="13" />
<TextBlock Text="{Binding Address}" Foreground="{StaticResource CoMutedBrush}"
FontFamily="Cascadia Mono,Consolas,monospace" FontSize="10" />
</StackPanel>
<TextBlock Grid.Column="2"
Text="{Binding PacketsReceived, StringFormat='↓{0}'}"
Foreground="{StaticResource CoMutedBrush}"
FontFamily="Cascadia Mono,Consolas,monospace" FontSize="11"
VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Row="2" Orientation="Horizontal" Spacing="8" Margin="0,6,0,0">
<Button Content="Kick" Command="{Binding KickCommand}" Padding="18,4" />
<Button Content="Ban" Command="{Binding BanCommand}" Padding="18,4"
Background="{StaticResource CoDangerBrush}" Foreground="White" />
<StackPanel Grid.Row="2" Orientation="Horizontal" Spacing="8"
HorizontalAlignment="Right" Margin="10,0,10,10">
<Button Content="Kick" Command="{Binding KickCommand}" Padding="22,5" />
<Button Classes="danger" Content="Ban" Command="{Binding BanCommand}" Padding="22,5" />
</StackPanel>
</Grid>
</Border>
</Grid>
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="Auto,*,Auto,Auto" Margin="0,14,0,0">
<TextBlock Grid.Column="0" Text="Status:" Foreground="{StaticResource CoTextBrush}"
VerticalAlignment="Center" Margin="0,0,6,0" />
<TextBlock Grid.Column="1" Text="{Binding StatusText}"
Foreground="{StaticResource CoAccentBrush}" FontWeight="Bold"
VerticalAlignment="Center" />
<Button Grid.Column="2" Content="Start" Command="{Binding StartCommand}"
Margin="0,0,8,0" Padding="26,7"
Background="{StaticResource CoAccentBrush}" Foreground="#0E120B" FontWeight="Bold" />
<Button Grid.Column="3" Content="Stop" Command="{Binding StopCommand}"
Padding="26,7"
Background="{StaticResource CoDangerBrush}" Foreground="White" FontWeight="Bold" />
</Grid>
<!-- ============ Control bar ============ -->
<Border Grid.Row="2" Background="{StaticResource CoBarBrush}"
BorderBrush="{StaticResource CoBorderBrush}" BorderThickness="0,1,0,0"
Padding="20,14">
<Grid ColumnDefinitions="*,Auto,Auto">
<StackPanel Grid.Column="0" Orientation="Horizontal" Spacing="8" VerticalAlignment="Center">
<TextBlock Text="" Foreground="{StaticResource CoMutedBrush}" FontSize="10"
VerticalAlignment="Center" />
<TextBlock Text="Local admin channel · 127.0.0.1"
Foreground="{StaticResource CoMutedBrush}" FontSize="11"
FontFamily="Cascadia Mono,Consolas,monospace" VerticalAlignment="Center" />
</StackPanel>
<Button Grid.Column="1" Classes="accent" Content="▶ START SERVER"
Command="{Binding StartCommand}" Margin="0,0,10,0" Padding="26,9"
FontSize="14" />
<Button Grid.Column="2" Classes="danger" Content="■ STOP"
Command="{Binding StopCommand}" Padding="26,9" FontSize="14" />
</Grid>
</Border>
</Grid>
</Window>