feat(tdd): implement SSOT canon, AGENTS.md, ultra-strict design audit, E2E scenarios, and Forgejo release pipeline
Some checks are pending
Forgejo Release / build-and-release (push) Waiting to run
Some checks are pending
Forgejo Release / build-and-release (push) Waiting to run
This commit is contained in:
parent
24aa70ae32
commit
4cd9c678c0
25 changed files with 1684 additions and 238 deletions
|
|
@ -97,17 +97,25 @@ public partial class App : Application
|
|||
|
||||
private async Task RunQuickAsync(IReadOnlyList<string> files, string outputExtension)
|
||||
{
|
||||
// 옵션 팝업~변환 경로 전체를 명시적 종료 모드로 먼저 감싼다.
|
||||
// 핵심(크래시 방지): 기본 OnLastWindowClose면 옵션 팝업(첫·유일 창)이 닫히는 순간 "마지막 창 종료" 규칙이
|
||||
// 발동해 앱이 종료 시퀀스에 진입하고, 직후 ShutdownMode 설정/변환이 InvalidOperationException으로 크래시한다.
|
||||
// (또한 진행 창을 닫아도 변환을 취소한 '뒤' 명시 종료해 ffmpeg 고아 프로세스를 막는다.)
|
||||
ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
|
||||
|
||||
// 빠른 변환 전, 출력 형식에 맞춘 간단 옵션 팝업.
|
||||
// '자세히 옵션…'이면 풀 UI(MainWindow)로 전환, '취소'면 종료, '변환'이면 선택 옵션으로 진행.
|
||||
var optWin = new QuickOptionsWindow(outputExtension, files.Count, Settings);
|
||||
var confirmed = optWin.ShowDialog();
|
||||
if (optWin.OpenFullUi) { ShowConvertDialog(files); return; }
|
||||
if (optWin.OpenFullUi)
|
||||
{
|
||||
// 풀 UI로 전환 — 종료 책임을 메인 창 수명(OnLastWindowClose)에 되돌린다.
|
||||
ShutdownMode = System.Windows.ShutdownMode.OnLastWindowClose;
|
||||
ShowConvertDialog(files);
|
||||
return;
|
||||
}
|
||||
if (confirmed != true) { Shutdown(0); return; }
|
||||
|
||||
// 변환 경로 동안은 명시적 종료 모드 — 진행 창을 닫아도 변환을 취소(ffmpeg 종료)한 '뒤' 앱을 종료한다.
|
||||
// (기본 OnLastWindowClose면 창 닫는 즉시 종료가 시작돼 ffmpeg가 고아로 백그라운드에 남는다.)
|
||||
ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
|
||||
|
||||
var logPath = Path.Combine(Path.GetTempPath(), "Everything2Everything_quick.log");
|
||||
var log = new System.Text.StringBuilder();
|
||||
log.AppendLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Quick start → {outputExtension}, {files.Count} file(s)");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>1.0.6</Version>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net9.0-windows10.0.19041.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
|
|
@ -35,3 +36,4 @@
|
|||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,17 @@
|
|||
<Setter Property="Foreground" Value="{StaticResource FsTextSecondary}"/>
|
||||
</Style>
|
||||
|
||||
<!-- Fluent typography aliases (Used across dialogs) -->
|
||||
<Style x:Key="TextSubtitle" TargetType="TextBlock" BasedOn="{StaticResource FsBodyStyle}">
|
||||
<Setter Property="FontSize" Value="16"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
</Style>
|
||||
<Style x:Key="TextCaption" TargetType="TextBlock" BasedOn="{StaticResource FsCaptionStyle}"/>
|
||||
<Style x:Key="TextBody" TargetType="TextBlock" BasedOn="{StaticResource FsBodyStyle}"/>
|
||||
<Style x:Key="TextBodyStrong" TargetType="TextBlock" BasedOn="{StaticResource FsBodyStyle}">
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
</Style>
|
||||
|
||||
<!-- Slider style: 2px track, 14px round thumb, blue fill up to value -->
|
||||
<Style x:Key="FsSliderStyle" TargetType="Slider">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@
|
|||
|
||||
<!-- AI Task -->
|
||||
<StackPanel x:Name="AiTaskPanel" Margin="0,0,0,32">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<Image Width="15" Height="15" VerticalAlignment="Center" Margin="0,0,6,0"
|
||||
RenderOptions.BitmapScalingMode="HighQuality"
|
||||
Source="pack://application:,,,/Assets/glyph-ai.png"/>
|
||||
|
|
@ -504,16 +504,17 @@
|
|||
Background="{StaticResource FsBgPanel}"
|
||||
BorderBrush="{StaticResource FsBorderSubtle}"
|
||||
BorderThickness="1" CornerRadius="20" Padding="4">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<ToggleButton x:Name="TabActiveBtn"
|
||||
Style="{StaticResource FsTabPillStyle}"
|
||||
Command="{Binding TabCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="Active">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<TextBlock Text="Active Queue" VerticalAlignment="Center"/>
|
||||
<Border Margin="8,0,0,0" Style="{StaticResource FsTabBadgeStyle}">
|
||||
<Border Margin="8,0,0,0" Style="{StaticResource FsTabBadgeStyle}" VerticalAlignment="Center">
|
||||
<TextBlock x:Name="TabActiveBadge" Text="0"
|
||||
FontSize="10" FontWeight="SemiBold"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{StaticResource FsTextTertiary}"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
|
@ -523,11 +524,12 @@
|
|||
Style="{StaticResource FsTabPillStyle}"
|
||||
Command="{Binding TabCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="Past">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<TextBlock Text="Past Results" VerticalAlignment="Center"/>
|
||||
<Border Margin="8,0,0,0" Style="{StaticResource FsTabBadgeStyle}">
|
||||
<Border Margin="8,0,0,0" Style="{StaticResource FsTabBadgeStyle}" VerticalAlignment="Center">
|
||||
<TextBlock x:Name="TabPastBadge" Text="0"
|
||||
FontSize="10" FontWeight="SemiBold"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{StaticResource FsTextTertiary}"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
|
@ -536,22 +538,47 @@
|
|||
</Border>
|
||||
|
||||
<!-- Actions -->
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||
<Button Content="⚙ 설정" Margin="0,0,8,0"
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<Button Margin="0,0,8,0"
|
||||
Style="{StaticResource FsSecondaryButtonStyle}"
|
||||
Command="{Binding SettingsCommand, RelativeSource={RelativeSource AncestorType=Window}}"/>
|
||||
<Button Content="Register Menu" Margin="0,0,8,0"
|
||||
Command="{Binding SettingsCommand, RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<ui:SymbolIcon Symbol="Settings24" FontSize="14" VerticalAlignment="Center" Margin="0,0,6,0"/>
|
||||
<TextBlock Text="설정" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button Margin="0,0,8,0"
|
||||
Style="{StaticResource FsSecondaryButtonStyle}"
|
||||
Command="{Binding RegisterCommand, RelativeSource={RelativeSource AncestorType=Window}}"/>
|
||||
<Button Content="Diagnose" Margin="0,0,8,0"
|
||||
Command="{Binding RegisterCommand, RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<ui:SymbolIcon Symbol="AppsAddIn24" FontSize="14" VerticalAlignment="Center" Margin="0,0,6,0"/>
|
||||
<TextBlock Text="우클릭 메뉴 등록" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button Margin="0,0,8,0"
|
||||
Style="{StaticResource FsSecondaryButtonStyle}"
|
||||
Command="{Binding DiagnoseCommand, RelativeSource={RelativeSource AncestorType=Window}}"/>
|
||||
<Button Content="Export Log" Margin="0,0,8,0"
|
||||
Command="{Binding DiagnoseCommand, RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<ui:SymbolIcon Symbol="Stethoscope24" FontSize="14" VerticalAlignment="Center" Margin="0,0,6,0"/>
|
||||
<TextBlock Text="진단" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button Margin="0,0,8,0"
|
||||
Style="{StaticResource FsSecondaryButtonStyle}"
|
||||
Command="{Binding ExportLogCommand, RelativeSource={RelativeSource AncestorType=Window}}"/>
|
||||
<Button x:Name="ClearAllButton" Content="Clear All"
|
||||
Command="{Binding ExportLogCommand, RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<ui:SymbolIcon Symbol="ArrowDownload24" FontSize="14" VerticalAlignment="Center" Margin="0,0,6,0"/>
|
||||
<TextBlock Text="로그 내보내기" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button x:Name="ClearAllButton" Margin="0,0,8,0"
|
||||
Style="{StaticResource FsSecondaryButtonStyle}"
|
||||
Command="{Binding ClearAllCommand, RelativeSource={RelativeSource AncestorType=Window}}"/>
|
||||
Command="{Binding ClearAllCommand, RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<ui:SymbolIcon Symbol="Delete24" FontSize="14" VerticalAlignment="Center" Margin="0,0,6,0"/>
|
||||
<TextBlock Text="목록 비우기" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
|
@ -700,9 +727,35 @@
|
|||
</Grid>
|
||||
|
||||
<!-- Past Results view (default) -->
|
||||
<ScrollViewer x:Name="PastResultsView" VerticalScrollBarVisibility="Auto"
|
||||
Padding="24">
|
||||
<ItemsControl x:Name="PastResultsList"
|
||||
<Grid x:Name="PastResultsContainer">
|
||||
<!-- 빈 상태 안내 (Empty State) -->
|
||||
<Grid x:Name="PastResultsEmpty" Visibility="Collapsed">
|
||||
<Border Background="{StaticResource FsBgBase}" Padding="32">
|
||||
<Grid MaxWidth="440" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Rectangle RadiusX="10" RadiusY="10"
|
||||
Stroke="{StaticResource FsBorderHairline}"
|
||||
StrokeThickness="1.25"
|
||||
StrokeDashArray="5 4"
|
||||
Fill="#04FFFFFF"/>
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Margin="48,52">
|
||||
<ui:SymbolIcon Symbol="History24" FontSize="48"
|
||||
Foreground="{StaticResource FsTextTertiary}"
|
||||
HorizontalAlignment="Center"/>
|
||||
<TextBlock Margin="0,16,0,0" FontSize="16" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource FsTextPrimary}"
|
||||
HorizontalAlignment="Center"
|
||||
Text="변환 이력이 없습니다"/>
|
||||
<TextBlock Margin="0,6,0,0" Style="{StaticResource FsCaptionStyle}"
|
||||
HorizontalAlignment="Center"
|
||||
TextAlignment="Center"
|
||||
Text="파일을 변환하면 완료된 내역과 절감된 용량이 여기에 기록됩니다"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
<ScrollViewer x:Name="PastResultsView" VerticalScrollBarVisibility="Auto"
|
||||
Padding="24">
|
||||
<ItemsControl x:Name="PastResultsList"
|
||||
ItemsSource="{Binding PastResults, RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
|
|
@ -813,6 +866,7 @@
|
|||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
<!-- /좌측 컬럼 끝 -->
|
||||
|
|
|
|||
|
|
@ -171,7 +171,8 @@ public partial class MainWindow : Wpf.Ui.Controls.FluentWindow
|
|||
TabPastBtn.IsChecked = tag == "Past";
|
||||
|
||||
ActiveQueueView.Visibility = tag == "Active" ? Visibility.Visible : Visibility.Collapsed;
|
||||
PastResultsView.Visibility = tag == "Past" ? Visibility.Visible : Visibility.Collapsed;
|
||||
PastResultsContainer.Visibility = tag == "Past" ? Visibility.Visible : Visibility.Collapsed;
|
||||
UpdatePastResultsVisibility();
|
||||
}
|
||||
|
||||
// ============== Drag & Drop ==============
|
||||
|
|
@ -247,11 +248,19 @@ public partial class MainWindow : Wpf.Ui.Controls.FluentWindow
|
|||
ActiveQueueScroll.Visibility = hasItems ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void UpdatePastResultsVisibility()
|
||||
{
|
||||
var hasItems = _pastResults.Count > 0;
|
||||
PastResultsEmpty.Visibility = hasItems ? Visibility.Collapsed : Visibility.Visible;
|
||||
PastResultsView.Visibility = hasItems ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void UpdateBadges()
|
||||
{
|
||||
TabActiveBadge.Text = _activeQueue.Count.ToString(CultureInfo.InvariantCulture);
|
||||
var count = _pastResults.Sum(g => g.Entries.Count);
|
||||
TabPastBadge.Text = count.ToString(CultureInfo.InvariantCulture);
|
||||
UpdatePastResultsVisibility();
|
||||
}
|
||||
|
||||
private void UpdateProcessQueueButton()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,13 @@
|
|||
WindowStartupLocation="CenterScreen"
|
||||
ResizeMode="NoResize"
|
||||
Closing="OnWindowClosing">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="FormatShiftTheme.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
|
|
|
|||
|
|
@ -6,9 +6,17 @@
|
|||
WindowStartupLocation="CenterOwner"
|
||||
ExtendsContentIntoTitleBar="True"
|
||||
WindowBackdropType="Mica"
|
||||
Background="{StaticResource FsBgBase}">
|
||||
Background="{DynamicResource FsBgBase}">
|
||||
|
||||
<Grid>
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="FormatShiftTheme.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid Background="{StaticResource FsBgBase}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
|
|
@ -51,10 +59,10 @@
|
|||
Style="{StaticResource FsSecondaryButtonStyle}" Margin="8,0,0,0"
|
||||
IsEnabled="False" Click="OnVerifyOpenAi"/>
|
||||
</Grid>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,16">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,0,0,16">
|
||||
<Ellipse x:Name="OpenAiDot" Style="{StaticResource FsLossDotStyle}"
|
||||
Fill="{StaticResource FsTextTertiary}" Margin="0,0,7,0"/>
|
||||
<TextBlock x:Name="OpenAiStatus" Text="키 미설정" Style="{StaticResource FsCaptionStyle}"/>
|
||||
Fill="{StaticResource FsTextTertiary}" Margin="0,0,7,0" VerticalAlignment="Center"/>
|
||||
<TextBlock x:Name="OpenAiStatus" Text="키 미설정" Style="{StaticResource FsCaptionStyle}" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Anthropic -->
|
||||
|
|
@ -68,23 +76,23 @@
|
|||
Style="{StaticResource FsPasswordInputStyle}"
|
||||
PasswordChanged="OnAnthropicKeyChanged"/>
|
||||
<Button x:Name="AnthropicVerifyBtn" Grid.Column="1" Content="확인"
|
||||
Style="{StaticResource FsSecondaryButtonStyle}" Margin="8,0,0,0"
|
||||
IsEnabled="False" Click="OnVerifyAnthropic"/>
|
||||
Style="{StaticResource FsSecondaryButtonStyle}" Margin="8,0,0,0"
|
||||
IsEnabled="False" Click="OnVerifyAnthropic"/>
|
||||
</Grid>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,16">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,0,0,16">
|
||||
<Ellipse x:Name="AnthropicDot" Style="{StaticResource FsLossDotStyle}"
|
||||
Fill="{StaticResource FsTextTertiary}" Margin="0,0,7,0"/>
|
||||
<TextBlock x:Name="AnthropicStatus" Text="키 미설정" Style="{StaticResource FsCaptionStyle}"/>
|
||||
Fill="{StaticResource FsTextTertiary}" Margin="0,0,7,0" VerticalAlignment="Center"/>
|
||||
<TextBlock x:Name="AnthropicStatus" Text="키 미설정" Style="{StaticResource FsCaptionStyle}" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Codex CLI (OAuth) -->
|
||||
<TextBlock Text="Codex CLI (OAuth · API 키 불필요)" Style="{StaticResource FsLabelStyle}" Margin="0,0,0,6"/>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,16">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,0,0,16">
|
||||
<Ellipse x:Name="CodexDot" Style="{StaticResource FsLossDotStyle}"
|
||||
Fill="{StaticResource FsTextTertiary}" Margin="0,0,7,0"/>
|
||||
Fill="{StaticResource FsTextTertiary}" Margin="0,0,7,0" VerticalAlignment="Center"/>
|
||||
<TextBlock x:Name="CodexStatus" Text="확인 중…" Style="{StaticResource FsCaptionStyle}" VerticalAlignment="Center"/>
|
||||
<Button x:Name="CodexVerifyBtn" Content="테스트" Style="{StaticResource FsSecondaryButtonStyle}"
|
||||
Margin="12,0,0,0" Padding="10,4" IsEnabled="False" Click="OnVerifyCodex"/>
|
||||
Margin="12,0,0,0" Padding="10,4" IsEnabled="False" Click="OnVerifyCodex" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 모델 -->
|
||||
|
|
@ -113,10 +121,10 @@
|
|||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<Ellipse x:Name="FfmpegDot" Style="{StaticResource FsLossDotStyle}"
|
||||
Fill="{StaticResource FsStatusWarn}" Margin="0,0,7,0"/>
|
||||
<TextBlock Text="FFmpeg" Style="{StaticResource FsBodyStyle}" FontWeight="Medium"/>
|
||||
Fill="{StaticResource FsStatusWarn}" Margin="0,0,7,0" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="FFmpeg" Style="{StaticResource FsBodyStyle}" FontWeight="Medium" VerticalAlignment="Center"/>
|
||||
<TextBlock x:Name="FfmpegStatus" Text="미설치" Style="{StaticResource FsCaptionStyle}" Margin="8,0,0,0" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
<TextBlock Text="영상/오디오 변환 (mp4·webm·mp3·flac…)" Style="{StaticResource FsCaptionStyle}" Margin="15,3,0,0"/>
|
||||
|
|
@ -134,10 +142,10 @@
|
|||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<Ellipse x:Name="LibreDot" Style="{StaticResource FsLossDotStyle}"
|
||||
Fill="{StaticResource FsStatusWarn}" Margin="0,0,7,0"/>
|
||||
<TextBlock Text="LibreOffice" Style="{StaticResource FsBodyStyle}" FontWeight="Medium"/>
|
||||
Fill="{StaticResource FsStatusWarn}" Margin="0,0,7,0" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="LibreOffice" Style="{StaticResource FsBodyStyle}" FontWeight="Medium" VerticalAlignment="Center"/>
|
||||
<TextBlock x:Name="LibreStatus" Text="미설치" Style="{StaticResource FsCaptionStyle}" Margin="8,0,0,0" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
<TextBlock Text="한글/Word/문서 변환 (HWP·DOCX→PDF/이미지). 한글은 H2Orestart 확장 필요." Style="{StaticResource FsCaptionStyle}" Margin="15,3,0,0" TextWrapping="Wrap"/>
|
||||
|
|
@ -155,9 +163,9 @@
|
|||
<!-- ===== 푸터 ===== -->
|
||||
<Border Grid.Row="2" Background="{StaticResource FsBgPanel}"
|
||||
BorderBrush="{StaticResource FsBorderSubtle}" BorderThickness="0,1,0,0" Padding="24,14">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Content="닫기" Style="{StaticResource FsSecondaryButtonStyle}" Padding="18,8" Click="OnClose"/>
|
||||
<Button Content="저장" Style="{StaticResource FsPrimaryButtonStyle}" Padding="22,8" Margin="8,0,0,0" Click="OnSave"/>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center">
|
||||
<Button Content="닫기" Style="{StaticResource FsSecondaryButtonStyle}" Padding="20,8" Click="OnClose"/>
|
||||
<Button Content="저장" Style="{StaticResource FsPrimaryButtonStyle}" Padding="20,8" Margin="8,0,0,0" Click="OnSave"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue