Baseline: WPF/Avalonia/Cli/Core + plans (BROWSER_FEATURES_PLAN v2, MOBILE_PLAN v1)

This commit is contained in:
Yun Chan 2026-08-15 11:59:25 +09:00
commit 21b7c4d8bd
60 changed files with 6581 additions and 0 deletions

View file

@ -0,0 +1,167 @@
<Window x:Class="VideoDownloader.App.SettingsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="설정" Height="600" Width="620"
FontFamily="{StaticResource UiFont}"
Background="{StaticResource WindowBgGradient}"
WindowStartupLocation="CenterOwner" ResizeMode="CanResize" ShowInTaskbar="False"
WindowStyle="None">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="0"
ResizeBorderThickness="6"
GlassFrameThickness="1"
CornerRadius="0"
UseAeroCaptionButtons="False"
NonClientFrameEdges="None"/>
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 캡션 (드래그 핸들 + 닫기) -->
<Border Grid.Row="0" Background="{StaticResource PanelBg}"
BorderBrush="{StaticResource BorderSubtle}" BorderThickness="0,0,0,1"
Padding="22,11,0,11" MouseLeftButtonDown="TitleBar_MouseDown">
<DockPanel>
<Button DockPanel.Dock="Right" Style="{StaticResource CloseButton}"
Content="&#xE8BB;" ToolTip="닫기" Click="Close_Click"/>
<TextBlock Text="설정" Foreground="{StaticResource TextPrimary}"
FontWeight="SemiBold" FontSize="14" VerticalAlignment="Center"/>
</DockPanel>
</Border>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" Padding="22,18">
<StackPanel>
<TextBlock Text="외관" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold"/>
<CheckBox Name="ThemeLightBox" Style="{StaticResource DarkCheckBox}"
Content="라이트 테마 사용 (적용 시 앱 재시작)" Margin="0,8,0,18"/>
<TextBlock Text="저장 폴더" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold"/>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="9" Margin="0,6,0,18">
<DockPanel>
<Button DockPanel.Dock="Right" Style="{StaticResource GhostButton}" Content="..." Padding="12,4" Margin="8,4,4,4" Click="BrowseFolder"/>
<TextBox Name="FolderBox" Style="{StaticResource DarkTextBox}" BorderThickness="0" Background="Transparent"/>
</DockPanel>
</Border>
<TextBlock Text="홈 페이지 (홈 버튼이 이동할 주소)" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold"/>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="9" Margin="0,6,0,18">
<TextBox Name="HomeBox" Style="{StaticResource DarkTextBox}" BorderThickness="0" Background="Transparent"/>
</Border>
<Grid Margin="0,0,0,18">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="12"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="12"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="세그먼트 동시 수" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold"/>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="9" Margin="0,6,0,0">
<TextBox Name="ConcurrencyBox" Style="{StaticResource DarkTextBox}" BorderThickness="0" Background="Transparent"/>
</Border>
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Text="최대 동시 항목" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold"/>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="9" Margin="0,6,0,0">
<TextBox Name="MaxConcurrentBox" Style="{StaticResource DarkTextBox}" BorderThickness="0" Background="Transparent"/>
</Border>
</StackPanel>
<StackPanel Grid.Column="4">
<TextBlock Text="최소 크기 (MB)" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold"/>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="9" Margin="0,6,0,0">
<TextBox Name="MinSizeBox" Style="{StaticResource DarkTextBox}" BorderThickness="0" Background="Transparent"/>
</Border>
</StackPanel>
</Grid>
<TextBlock Text="ffmpeg 경로" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold"/>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="9" Margin="0,6,0,4">
<DockPanel>
<Button DockPanel.Dock="Right" Style="{StaticResource GhostButton}" Content="..." Padding="12,4" Margin="8,4,4,4" Click="BrowseFfmpeg"/>
<TextBox Name="FfmpegBox" Style="{StaticResource DarkTextBox}" BorderThickness="0" Background="Transparent"/>
</DockPanel>
</Border>
<TextBlock Text="비워두면 시스템 PATH 의 ffmpeg 사용 (HLS→MP4 리먹스)" FontSize="11" Foreground="{StaticResource TextMuted}" Margin="0,0,0,18"/>
<TextBlock Text="소셜 영상 (YouTube·Instagram·X)" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold"/>
<TextBlock Text="yt-dlp 로 소셜 사이트 영상을 받습니다" FontSize="11" Foreground="{StaticResource TextMuted}" Margin="0,2,0,8"/>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="9" Margin="0,0,0,4">
<DockPanel>
<Button DockPanel.Dock="Right" Style="{StaticResource GhostButton}" Content="재설치" Padding="12,4" Margin="4,4,8,4" ToolTip="yt-dlp 최신 버전으로 다시 다운로드" Click="ReinstallYtDlp_Click"/>
<Button DockPanel.Dock="Right" Style="{StaticResource GhostButton}" Content="..." Padding="12,4" Margin="4,4,4,4" Click="BrowseYtDlp"/>
<TextBox Name="YtDlpBox" Style="{StaticResource DarkTextBox}" BorderThickness="0" Background="Transparent"/>
</DockPanel>
</Border>
<TextBlock Text="비워두면 자동/PATH 의 yt-dlp 사용" FontSize="11" Foreground="{StaticResource TextMuted}" Margin="0,0,0,10"/>
<WrapPanel Orientation="Horizontal" Margin="0,0,0,14">
<CheckBox Name="UseCookiesBox" Style="{StaticResource DarkCheckBox}" Content="로그인 필요 영상을 위해 브라우저 쿠키 사용" Margin="4,4"/>
<CheckBox Name="AutoInstallBox" Style="{StaticResource DarkCheckBox}" Content="yt-dlp 가 없으면 자동 다운로드" Margin="4,4"/>
<CheckBox Name="AutoUpdateBox" Style="{StaticResource DarkCheckBox}" Content="YouTube 차단 시 yt-dlp 자동 갱신 후 재시도" Margin="4,4"/>
<CheckBox Name="AutoInstallDenoBox" Style="{StaticResource DarkCheckBox}" Content="Deno(JS 런타임) 자동 설치 — YouTube 차단 해제용" Margin="4,4"/>
</WrapPanel>
<StackPanel Margin="0,0,0,18">
<TextBlock Text="기본 화질" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold"/>
<ComboBox Name="DefaultQualityBox" Style="{StaticResource DarkComboBox}" SelectedValuePath="Tag" Margin="0,6,0,0">
<ComboBoxItem Content="최고 화질 (MP4)" Tag="best"/>
<ComboBoxItem Content="1080p" Tag="1080"/>
<ComboBoxItem Content="720p" Tag="720"/>
<ComboBoxItem Content="480p" Tag="480"/>
<ComboBoxItem Content="360p" Tag="360"/>
<ComboBoxItem Content="오디오만 (MP3)" Tag="audio"/>
</ComboBox>
</StackPanel>
<StackPanel Margin="0,0,0,18">
<TextBlock Text="YouTube 클라이언트 (고급)" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold"/>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="9" Margin="0,6,0,0">
<TextBox Name="YoutubeClientsBox" Style="{StaticResource DarkTextBox}" BorderThickness="0" Background="Transparent"/>
</Border>
<TextBlock Text="비워두면 yt-dlp 기본값 사용(권장). 봇 차단/PO 토큰 오류 시 예: tv,android_vr,web" FontSize="11" Foreground="{StaticResource TextMuted}" Margin="0,4,0,0" TextWrapping="Wrap"/>
</StackPanel>
<TextBlock Text="브라우저 데이터" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold" Margin="0,0,0,2"/>
<TextBlock x:Name="ProfileModeText" Text="" FontSize="11" Foreground="{StaticResource TextMuted}" Margin="0,0,0,8" TextWrapping="Wrap"/>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="9" Margin="0,0,0,18">
<DockPanel>
<Button DockPanel.Dock="Right" Style="{StaticResource GhostButton}" Content="삭제" Padding="12,4" Margin="8,4,4,4"
ToolTip="쿠키·localStorage·캐시 삭제 (현재 프로필)" Click="ClearData_Click"/>
<TextBox x:Name="ProfilePathBox" Style="{StaticResource DarkTextBox}" BorderThickness="0" Background="Transparent" IsReadOnly="True"/>
</DockPanel>
</Border>
<TextBlock Text="반응할 형식" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold"/>
<TextBlock Text="체크된 형식만 자동 감지/다운로드합니다" FontSize="11" Foreground="{StaticResource TextMuted}" Margin="0,2,0,10"/>
<WrapPanel Orientation="Horizontal">
<CheckBox Name="FmtHls" Style="{StaticResource DarkCheckBox}" Content="HLS (m3u8)" Margin="4,5"/>
<CheckBox Name="FmtDash" Style="{StaticResource DarkCheckBox}" Content="DASH (.mpd)" Margin="4,5"/>
<CheckBox Name="FmtMp4" Style="{StaticResource DarkCheckBox}" Content="MP4" Margin="4,5"/>
<CheckBox Name="FmtWebM" Style="{StaticResource DarkCheckBox}" Content="WebM" Margin="4,5"/>
<CheckBox Name="FmtMkv" Style="{StaticResource DarkCheckBox}" Content="MKV" Margin="4,5"/>
<CheckBox Name="FmtM4v" Style="{StaticResource DarkCheckBox}" Content="M4V" Margin="4,5"/>
<CheckBox Name="FmtMov" Style="{StaticResource DarkCheckBox}" Content="MOV" Margin="4,5"/>
<CheckBox Name="FmtAvi" Style="{StaticResource DarkCheckBox}" Content="AVI" Margin="4,5"/>
<CheckBox Name="FmtAudio" Style="{StaticResource DarkCheckBox}" Content="오디오 (m4a/mp3/ogg...)" Margin="4,5"/>
</WrapPanel>
</StackPanel>
</ScrollViewer>
<Border Grid.Row="2" BorderBrush="{StaticResource BorderSubtle}" BorderThickness="0,1,0,0" Padding="22,12">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Style="{StaticResource GhostButton}" Content="취소" Width="90" Margin="0,0,8,0" IsCancel="True"/>
<Button Style="{StaticResource PrimaryButton}" Content="확인" Width="90" Click="Ok_Click" IsDefault="True"/>
</StackPanel>
</Border>
</Grid>
</Window>