업데이트 안내창 디자인 변경 - 제목줄 제거, accent 띠·아이콘 칩·버전 비교 박스

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
최민영 2026-09-21 22:26:56 +09:00
parent 83d207462f
commit 649599de48
7 changed files with 129 additions and 115 deletions

2
dist/README.txt vendored
View File

@ -1,5 +1,5 @@
UbisamBase 플랫폼 배포 폴더 (빌드할 때 자동 생성 - 직접 고치지 마세요)
갱신 시각 : 2026-09-21 22:17:54
갱신 시각 : 2026-09-21 22:26:56
빌드 구성 : Release
원본 소스 : D:\업무\03_개발\Source\용접기\08_UbisamPlatform\
----

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,4 +1,4 @@
{
"version": "2026-09-21 22:17:54",
"version": "2026-09-21 22:26:56",
"configuration": "Release"
}

View File

@ -1,7 +1,7 @@
<Window x:Class="UbisamBase.Launcher.UpdateDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="440"
Width="460"
SizeToContent="Height"
WindowStyle="None"
ResizeMode="NoResize"
@ -10,37 +10,52 @@
WindowStartupLocation="CenterScreen"
FontFamily="Barlow, Segoe UI"
FontSize="14"
MouseLeftButtonDown="Window_MouseLeftButtonDown"
PreviewKeyDown="Window_PreviewKeyDown">
<!-- Core의 MessageDialog와 같은 생김새지만 리소스를 공유하지 않는다 — Launcher가 Core를 참조하면
갱신 대상인 Core.dll을 먼저 물고 있게 되어 덮어쓸 수 없기 때문이다(PlatformUpdater 주석 참고).
그래서 색은 코드비하인드가 시스템 테마(밝게/어둡게)에 맞춰 직접 넣는다. -->
<!-- 제목줄 없이 한 판으로 가고, 위쪽 accent 띠 하나로 플랫폼 창임을 표시한다.
Core의 리소스를 쓸 수 없어(참조하면 갱신 대상 Core.dll을 물게 된다) 색은 코드비하인드가
시스템 테마(밝게/어둡게)에 맞춰 직접 넣는다. -->
<Window.Resources>
<!-- 버튼: 채움색·글자색은 코드에서 넣고, 여기서는 모양과 hover 반응만 정의한다. -->
<Style x:Key="DialogButton" TargetType="Button">
<Setter Property="MinWidth" Value="84"/>
<Setter Property="Padding" Value="14,7"/>
<Setter Property="BorderThickness" Value="1"/>
<Style x:Key="PrimaryButton" TargetType="Button">
<Setter Property="MinWidth" Value="104"/>
<Setter Property="Padding" Value="16,9"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="6"
SnapsToDevicePixels="True">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="{TemplateBinding Padding}"/>
<Border x:Name="Bd" Background="{TemplateBinding Background}" CornerRadius="7" SnapsToDevicePixels="True">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Margin="{TemplateBinding Padding}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Opacity" Value="0.85"/>
<Setter TargetName="Bd" Property="Opacity" Value="0.88"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Bd" Property="Opacity" Value="0.7"/>
<Setter TargetName="Bd" Property="Opacity" Value="0.72"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- 보조 동작은 테두리 없는 글자 버튼 — 눈이 "업데이트" 쪽으로 먼저 가게 한다. -->
<Style x:Key="QuietButton" TargetType="Button">
<Setter Property="MinWidth" Value="84"/>
<Setter Property="Padding" Value="14,9"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}" CornerRadius="7" SnapsToDevicePixels="True">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Margin="{TemplateBinding Padding}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{Binding QuietHoverBrush, RelativeSource={RelativeSource AncestorType=Window}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
@ -51,81 +66,77 @@
<Border x:Name="RootBorder" BorderThickness="1">
<DockPanel>
<!-- 위쪽 accent 띠 -->
<Border x:Name="AccentStrip" DockPanel.Dock="Top" Height="3"/>
<!-- 제목줄: 끌어서 창 이동 -->
<Border x:Name="TitleBar"
DockPanel.Dock="Top"
BorderThickness="0,0,0,1"
Padding="16,10"
MouseLeftButtonDown="TitleBar_MouseLeftButtonDown">
<TextBlock x:Name="TitleText" Text="UbisamBase 업데이트" FontWeight="SemiBold"/>
</Border>
<!-- 버튼줄: 예가 주 동작(accent 채움), 아니오가 보조(외곽선) -->
<Border x:Name="ButtonBar"
DockPanel.Dock="Bottom"
BorderThickness="0,1,0,0"
Padding="16,12">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="NoButton"
Content="나중에"
Style="{StaticResource DialogButton}"
Margin="0,0,8,0"
Click="No_Click"/>
<Button x:Name="YesButton"
Content="업데이트"
Style="{StaticResource DialogButton}"
IsDefault="True"
Click="Yes_Click"/>
</StackPanel>
</Border>
<!-- 본문: 아이콘 + 안내문 + 버전 비교 -->
<Grid Margin="20,20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Margin="26,24,26,20">
<!-- 제목줄: 아이콘 칩 + 제목/한 줄 설명 -->
<StackPanel Orientation="Horizontal">
<Border x:Name="IconChip" Width="44" Height="44" CornerRadius="22" VerticalAlignment="Top" Margin="0,0,16,0">
<!-- 아래로 내려받는 화살표 -->
<Path x:Name="IconPath"
Grid.Column="0"
Data="M3,12 A9,9 0 0 1 21,12 A9,9 0 0 1 3,12 Z M9.3,9.3 A2.7,2.7 0 1 1 13.3,12.6 C12.5,13.1 12,13.6 12,14.8 M12,17.4 L12,17.5"
Width="24" Height="24"
StrokeThickness="1.5"
Data="M12,4 L12,14.5 M7.2,10 L12,15 L16.8,10 M5.5,19 L18.5,19"
Width="22" Height="22"
Stretch="Uniform"
StrokeThickness="1.7"
StrokeStartLineCap="Round"
StrokeEndLineCap="Round"
StrokeLineJoin="Round"
VerticalAlignment="Top"
Margin="0,0,14,0"/>
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<StackPanel Grid.Column="1">
<StackPanel VerticalAlignment="Center">
<TextBlock x:Name="HeadlineText"
Text="새 플랫폼 버전이 있습니다."
TextWrapping="Wrap"
Margin="0,0,0,14"/>
Text="새 버전이 준비됐습니다"
FontFamily="Barlow Condensed, Segoe UI"
FontSize="21"
FontWeight="SemiBold"/>
<TextBlock x:Name="SubText"
Text="플랫폼을 최신으로 바꾼 뒤 실행합니다."
FontSize="13"
Margin="0,3,0,0"/>
</StackPanel>
</StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 버전 비교: 지금 → 새것 -->
<Border x:Name="VersionBox" CornerRadius="8" Padding="16,13" Margin="0,20,0,0">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<StackPanel>
<TextBlock x:Name="CurrentLabel" Text="지금" FontSize="11" HorizontalAlignment="Center"/>
<TextBlock x:Name="CurrentValue" FontSize="13" Margin="0,3,0,0" HorizontalAlignment="Center"/>
</StackPanel>
<TextBlock x:Name="CurrentLabel" Grid.Row="0" Grid.Column="0" Text="지금 버전" Margin="0,0,14,4"/>
<TextBlock x:Name="CurrentValue" Grid.Row="0" Grid.Column="1" Margin="0,0,0,4"/>
<TextBlock x:Name="NewLabel" Grid.Row="1" Grid.Column="0" Text="새 버전" Margin="0,0,14,0"/>
<TextBlock x:Name="NewValue" Grid.Row="1" Grid.Column="1" FontWeight="SemiBold"/>
</Grid>
<Path x:Name="ArrowPath"
Data="M4,10 L18,10 M13,5.5 L18,10 L13,14.5"
Width="22" Height="20"
Stretch="Uniform"
StrokeThickness="1.6"
StrokeStartLineCap="Round"
StrokeEndLineCap="Round"
StrokeLineJoin="Round"
Margin="18,10,18,0"
VerticalAlignment="Center"/>
<StackPanel>
<TextBlock x:Name="NewLabel" Text="새 버전" FontSize="11" HorizontalAlignment="Center"/>
<TextBlock x:Name="NewValue" FontSize="13" FontWeight="SemiBold" Margin="0,3,0,0" HorizontalAlignment="Center"/>
</StackPanel>
</StackPanel>
</Border>
<TextBlock x:Name="FootnoteText"
Text="지금 받으면 새 버전으로 실행합니다. 나중에를 누르면 이번에는 그대로 실행하고, 다음에 다시 물어봅니다."
Text="나중에를 누르면 이번에는 지금 버전으로 실행하고, 다음에 다시 물어봅니다."
FontSize="12"
TextWrapping="Wrap"
Margin="0,14,0,0"/>
Margin="2,14,0,0"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,22,0,0">
<Button x:Name="NoButton" Content="나중에" Style="{StaticResource QuietButton}" Margin="0,0,8,0" Click="No_Click"/>
<Button x:Name="YesButton" Content="지금 업데이트" Style="{StaticResource PrimaryButton}" IsDefault="True" Click="Yes_Click"/>
</StackPanel>
</StackPanel>
</Grid>
</DockPanel>
</Border>
</Window>

View File

@ -7,11 +7,11 @@ using Microsoft.Win32;
namespace UbisamBase.Launcher;
/// <summary>
/// "새 버전이 있습니다 — 지금 받을까요?" 대화상자. 플랫폼(Core)의 MessageDialog와 같은 생김새지만,
/// Launcher는 Core를 참조하지 않으므로(참조하면 갱신 대상인 Core.dll을 물고 있게 된다) 색을 직접 넣는다.
/// "새 버전이 준비됐습니다 — 지금 받을까요?" 대화상자.
///
/// 테마는 윈도우 설정(밝게/어둡게)을 따라간다 — 이 시점에는 아직 앱의 UI 설정을 읽을 수 없기 때문이다.
/// 색 값은 Core의 Colors.Dark.xaml / Colors.Light.xaml에서 같은 이름으로 가져온 것이다.
/// 플랫폼(Core)의 색·글꼴을 따르되 리소스는 공유하지 않는다 — Launcher가 Core를 참조하면 갱신
/// 대상인 Core.dll을 물고 있게 되어 덮어쓸 수 없기 때문이다. 그래서 색을 여기서 직접 넣는다.
/// 테마는 윈도우 설정(밝게/어둡게)을 따른다. 이 시점에는 아직 앱의 UI 설정을 읽을 수 없다.
/// </summary>
public partial class UpdateDialog : Window
{
@ -25,50 +25,52 @@ public partial class UpdateDialog : Window
ApplyTheme(IsSystemLightTheme());
}
/// <summary>대화상자를 띄우고 "업데이트"를 눌렀는지 돌려준다.</summary>
/// <summary>보조 버튼에 마우스를 올렸을 때 깔리는 색. 템플릿에서 바인딩해 쓴다.</summary>
public Brush QuietHoverBrush { get; private set; } = Brushes.Transparent;
/// <summary>대화상자를 띄우고 "지금 업데이트"를 눌렀는지 돌려준다.</summary>
public static bool Ask(string currentVersion, string newVersion)
=> new UpdateDialog(currentVersion, newVersion).ShowDialog() == true;
private void ApplyTheme(bool light)
{
// Colors.Light.xaml / Colors.Dark.xaml 과 같은 값.
var background = Color(light ? "#FFF2F2F3" : "#FF23262B");
var foreground = Color(light ? "#FF1D1F20" : "#FFE8EAED");
var panel = Color(light ? "#FFFFFFFF" : "#FF2A2E34");
var border = Color(light ? "#FFD6D6D9" : "#FF3A3F47");
var muted = Color(light ? "#FF98989B" : "#FF8A9099");
var accentFill = Color(light ? "#FF1D82E8" : "#FF1E7FD4");
var onAccent = Color(light ? "#FFFFFFFF" : "#FFF2F7FC");
var background = Brush(light ? "#FFFFFFFF" : "#FF2A2E34");
var foreground = Brush(light ? "#FF1D1F20" : "#FFE8EAED");
var border = Brush(light ? "#FFD6D6D9" : "#FF3A3F47");
var muted = Brush(light ? "#FF98989B" : "#FF8A9099");
var accent = Brush(light ? "#FF2196F3" : "#FF4DA6F5");
var accentFill = Brush(light ? "#FF1D82E8" : "#FF1E7FD4");
var onAccent = Brush(light ? "#FFFFFFFF" : "#FFF2F7FC");
var sunken = Brush(light ? "#FFF2F2F3" : "#FF23262B");
var chip = Brush(light ? "#142196F3" : "#1F4DA6F5");
Background = background;
Foreground = foreground;
RootBorder.BorderBrush = border;
AccentStrip.Background = accent;
TitleBar.Background = panel;
TitleBar.BorderBrush = border;
TitleText.Foreground = foreground;
IconChip.Background = chip;
IconPath.Stroke = accent;
ButtonBar.Background = panel;
ButtonBar.BorderBrush = border;
IconPath.Stroke = foreground;
HeadlineText.Foreground = foreground;
SubText.Foreground = muted;
VersionBox.Background = sunken;
CurrentLabel.Foreground = muted;
NewLabel.Foreground = muted;
CurrentValue.Foreground = muted;
ArrowPath.Stroke = accent;
NewLabel.Foreground = muted;
NewValue.Foreground = foreground;
FootnoteText.Foreground = muted;
YesButton.Background = accentFill;
YesButton.BorderBrush = accentFill;
YesButton.Foreground = onAccent;
NoButton.Background = Brushes.Transparent;
NoButton.BorderBrush = border;
NoButton.Foreground = foreground;
NoButton.Foreground = muted;
QuietHoverBrush = sunken;
}
private static SolidColorBrush Color(string hex)
private static SolidColorBrush Brush(string hex)
=> new SolidColorBrush((Color)ColorConverter.ConvertFromString(hex));
/// <summary>윈도우가 밝은 테마인지. Core의 UiSettingsService.IsSystemLightTheme과 같은 판정이다.</summary>
@ -87,7 +89,8 @@ public partial class UpdateDialog : Window
}
}
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => DragMove();
/// <summary>제목줄이 없으므로 창 아무 데나 끌어서 옮길 수 있게 한다.</summary>
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => DragMove();
private void Yes_Click(object sender, RoutedEventArgs e) => DialogResult = true;