Files
OwnCord/Client/OwnCord.Client/Themes/Controls.xaml
T
jevb c1c25ed26c feat: implement full client UI from mockup — 10 phases, 331 tests
Client UI:
- Design system: Colors, Typography, Controls resource dictionaries
- Message actions: reply compose bar, hover edit/delete/reply buttons
- Rich content: code blocks, attachments, system messages, content parser
- Server strip: 72px sidebar with server icons, home button, add server
- Status picker: popup for changing online/idle/dnd/invisible status
- ConnectPage: server health check dots with auto-refresh
- User popup: profile card with banner, avatar, roles, member since
- Emoji picker: 6 categories, search, grid of Unicode emojis
- Settings overlay: full-screen with sidebar navigation
- Friends/DM view: sidebar + friends list with tabs (online/all/pending)
- Toast notifications: auto-dismiss after 3s with fade animation

Models & services:
- Attachment model added to Message, ApiMessage, ChatMessagePayload
- EditMessageAsync, DeleteMessageAsync, SendStatusChangeAsync APIs
- MessageContentParser (code blocks, inline code, bold, italic)
- EmojiData, ToastService, HealthStatusToBrushConverter

Server (from prior session):
- Voice room management, SFU, speaker detection
- ACME/TLS support, config improvements
- Protocol and schema updates

Tests: 331 passing (61 converter + 24 voice service + 34 voice VM +
41 parser + 9 edit/delete + existing)
2026-03-15 11:42:25 +01:00

286 lines
15 KiB
XML

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- ═══ TextBox ═══ -->
<Style x:Key="ModernTextBox" TargetType="TextBox">
<Setter Property="Background" Value="{StaticResource BgTertiary}"/>
<Setter Property="Foreground" Value="{StaticResource TextNormal}"/>
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="12,10"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontFamily" Value="{StaticResource FontBody}"/>
<Setter Property="CaretBrush" Value="{StaticResource TextNormal}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="4">
<ScrollViewer x:Name="PART_ContentHost" Margin="{TemplateBinding Padding}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" Value="{StaticResource Accent}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{StaticResource BorderStrong}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ═══ PasswordBox ═══ -->
<Style x:Key="ModernPasswordBox" TargetType="PasswordBox">
<Setter Property="Background" Value="{StaticResource BgTertiary}"/>
<Setter Property="Foreground" Value="{StaticResource TextNormal}"/>
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="12,10"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontFamily" Value="{StaticResource FontBody}"/>
<Setter Property="CaretBrush" Value="{StaticResource TextNormal}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="PasswordBox">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="4">
<ScrollViewer x:Name="PART_ContentHost" Margin="{TemplateBinding Padding}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" Value="{StaticResource Accent}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{StaticResource BorderStrong}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ═══ Primary Button ═══ -->
<Style x:Key="PrimaryButton" TargetType="Button">
<Setter Property="Background" Value="{StaticResource Accent}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="FontFamily" Value="{StaticResource FontBody}"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}"
CornerRadius="4" Padding="16,12">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource AccentHover}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource AccentActive}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource BorderStrong}"/>
<Setter Property="Foreground" Value="{StaticResource TextFaint}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ═══ Ghost / Secondary Button ═══ -->
<Style x:Key="GhostButton" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="#b5bac1"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="FontFamily" Value="{StaticResource FontBody}"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}"
CornerRadius="4" Padding="10,6">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource BgSecondary}"/>
<Setter Property="Foreground" Value="{StaticResource TextNormal}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource BorderStrong}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ═══ Danger Button ═══ -->
<Style x:Key="DangerButton" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource TextFaint}"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}"
CornerRadius="4" Padding="6,4">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="#da373c"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ═══ Edit Button ═══ -->
<Style x:Key="EditButton" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource TextFaint}"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}"
CornerRadius="4" Padding="6,4">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource BgActive}"/>
<Setter Property="Foreground" Value="{StaticResource TextNormal}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ═══ Link Button ═══ -->
<Style x:Key="LinkButton" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource TextLink}"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="FontFamily" Value="{StaticResource FontBody}"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock x:Name="Tb" Text="{TemplateBinding Content}"
Foreground="{TemplateBinding Foreground}"/>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Tb" Property="TextDecorations" Value="Underline"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ═══ Modern CheckBox ═══ -->
<Style x:Key="ModernCheckBox" TargetType="CheckBox">
<Setter Property="Foreground" Value="#b5bac1"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="FontFamily" Value="{StaticResource FontBody}"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<StackPanel Orientation="Horizontal">
<Border x:Name="CheckBorder" Width="18" Height="18"
CornerRadius="4" BorderThickness="2"
BorderBrush="{StaticResource BorderStrong}" Background="Transparent"
VerticalAlignment="Center" Margin="0,0,8,0">
<TextBlock x:Name="CheckMark" Text="&#x2713;"
FontSize="12" FontWeight="Bold"
Foreground="White" HorizontalAlignment="Center"
VerticalAlignment="Center" Visibility="Collapsed"/>
</Border>
<ContentPresenter VerticalAlignment="Center"/>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="CheckBorder" Property="Background" Value="{StaticResource Accent}"/>
<Setter TargetName="CheckBorder" Property="BorderBrush" Value="{StaticResource Accent}"/>
<Setter TargetName="CheckMark" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="CheckBorder" Property="BorderBrush" Value="{StaticResource Accent}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ═══ Small Icon Button ═══ -->
<Style x:Key="SmallIconButton" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource TextFaint}"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}"
CornerRadius="4" Padding="8,5">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource BgActive}"/>
<Setter Property="Foreground" Value="{StaticResource TextNormal}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ═══ Header Tool Button (chat header icons) ═══ -->
<Style x:Key="HeaderToolButton" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource TextMuted}"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Width" Value="32"/>
<Setter Property="Height" Value="32"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}"
CornerRadius="4">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource BgHover}"/>
<Setter Property="Foreground" Value="{StaticResource TextNormal}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>