releases/VideoDownloader.App/MainWindow.xaml

701 lines
50 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<Window x:Class="VideoDownloader.App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
xmlns:vm="clr-namespace:VideoDownloader.App.ViewModels"
xmlns:local="clr-namespace:VideoDownloader.App"
xmlns:feat="clr-namespace:VideoDownloader.App.Browser.Features"
mc:Ignorable="d"
FontFamily="{StaticResource UiFont}"
Title="Video Downloader" Height="820" Width="1300"
Background="{StaticResource WindowBgGradient}"
WindowStartupLocation="CenterScreen"
WindowStyle="None" ResizeMode="CanResize">
<!-- 보더리스: WindowChrome 이 실제 엣지 리사이즈 + 올바른 최대화(작업표시줄 존중) + DWM 그림자 담당 -->
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="0"
ResizeBorderThickness="6"
GlassFrameThickness="1"
CornerRadius="0"
UseAeroCaptionButtons="False"
NonClientFrameEdges="None"/>
</WindowChrome.WindowChrome>
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
<DataTemplate DataType="{x:Type vm:DownloadItemViewModel}">
<Border Background="{StaticResource CardBg}" BorderBrush="{StaticResource BorderSubtle}"
BorderThickness="1" CornerRadius="12" Padding="13" Margin="0,0,0,10">
<StackPanel>
<DockPanel>
<Border DockPanel.Dock="Right" Background="{StaticResource GlassBg}"
BorderBrush="{StaticResource BorderBrush}" BorderThickness="1"
CornerRadius="6" Padding="8,2" VerticalAlignment="Center">
<TextBlock Text="{Binding FormatTag}" FontSize="10" FontWeight="Bold"
Foreground="{StaticResource AccentBrush}"/>
</Border>
<TextBlock Text="{Binding Title}" Foreground="{StaticResource TextPrimary}"
FontSize="13" FontWeight="SemiBold" TextTrimming="CharacterEllipsis"
VerticalAlignment="Center"/>
</DockPanel>
<!-- 소셜(YouTube/Instagram/X) 카드: 화질 선택 -->
<DockPanel Margin="0,9,0,2" Visibility="{Binding IsSocial, Converter={StaticResource BoolToVis}}">
<Button DockPanel.Dock="Right" Click="CardFetchFormats_Click" Margin="7,0,0,0"
VerticalAlignment="Center" ToolTip="이 영상에서 사용 가능한 화질 조회">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource CardActionButton}">
<Setter Property="Content" Value="불러오기"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsFetchingFormats}" Value="True">
<Setter Property="Content" Value="…"/>
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="다운로드 중"><Setter Property="IsEnabled" Value="False"/></DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="병합 중"><Setter Property="IsEnabled" Value="False"/></DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="리먹스 중"><Setter Property="IsEnabled" Value="False"/></DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="완료"><Setter Property="IsEnabled" Value="False"/></DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<ComboBox Style="{StaticResource DarkComboBox}"
ItemsSource="{Binding Formats}" DisplayMemberPath="Label"
SelectedItem="{Binding SelectedFormat}"
VerticalAlignment="Center"/>
</DockPanel>
<DockPanel Margin="0,11,0,6">
<TextBlock DockPanel.Dock="Right" Text="{Binding Segments}"
Foreground="{StaticResource TextMuted}" FontSize="11"
VerticalAlignment="Center" Margin="8,0,0,0"/>
<Grid VerticalAlignment="Center">
<ProgressBar Value="{Binding Progress}" Maximum="100">
<ProgressBar.Style>
<Style TargetType="ProgressBar" BasedOn="{StaticResource AccentProgressBar}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsIndeterminate}" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ProgressBar.Style>
</ProgressBar>
<ProgressBar>
<ProgressBar.Style>
<Style TargetType="ProgressBar" BasedOn="{StaticResource IndeterminateBar}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsIndeterminate}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ProgressBar.Style>
</ProgressBar>
</Grid>
</DockPanel>
<DockPanel Margin="0,4,0,0">
<TextBlock Text="{Binding Status}" FontSize="11" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource TextSecondary}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Status}" Value="오류">
<Setter Property="Foreground" Value="{StaticResource ErrorBrush}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="완료">
<Setter Property="Foreground" Value="{StaticResource SuccessBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal">
<Button Style="{StaticResource CardActionButton}" Content="받기" Click="CardDownload_Click" Margin="0,0,6,0"/>
<Button Content="취소" Click="CardCancel_Click" Margin="0,0,6,0">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource CardActionButton}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Status}" Value="다운로드 중"><Setter Property="IsEnabled" Value="True"/></DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="병합 중"><Setter Property="IsEnabled" Value="True"/></DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="리먹스 중"><Setter Property="IsEnabled" Value="True"/></DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Style="{StaticResource CardActionButton}" Content="재시도" Click="CardRetry_Click" Margin="0,0,6,0"/>
<Button Style="{StaticResource CardActionButton}" Content="폴더" Click="CardFolder_Click"/>
</StackPanel>
</DockPanel>
<StackPanel Orientation="Horizontal" Margin="0,8,0,0">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Status}" Value="오류">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<TextBlock Text="&#xE7BA;" Style="{StaticResource FluentIcon}" Foreground="{StaticResource ErrorBrush}" FontSize="13" Margin="0,0,6,0"/>
<TextBlock Text="{Binding Error}" Foreground="{StaticResource ErrorBrush}" FontSize="11" TextWrapping="Wrap" MaxWidth="300"/>
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- ===== 상단 툴바 (슬림, 전체가 드래그 핸들) ===== -->
<Border x:Name="ToolbarRow" Grid.Row="0" Background="{StaticResource PanelBg}"
BorderBrush="{StaticResource AccentFadeBrush}" BorderThickness="0,0,0,2" Padding="20,9,0,9"
PreviewMouseLeftButtonDown="TitleBar_PreviewMouseLeftButtonDown">
<DockPanel>
<!-- 브랜드 -->
<StackPanel DockPanel.Dock="Left" Orientation="Horizontal"
VerticalAlignment="Center" Margin="0,0,12,0">
<Border Width="26" Height="26" CornerRadius="7" Background="{StaticResource AccentGradient}">
<TextBlock Text="&#xE896;" Style="{StaticResource FluentIcon}" Foreground="White" FontSize="14"/>
</Border>
<TextBlock Text="Video Downloader" Foreground="{StaticResource TextPrimary}"
FontWeight="SemiBold" FontSize="13.5" VerticalAlignment="Center" Margin="9,0,0,0"/>
</StackPanel>
<!-- 네비게이션 (Fluent 아이콘) -->
<StackPanel DockPanel.Dock="Left" Orientation="Horizontal" VerticalAlignment="Center">
<Button Name="NavBack" Style="{StaticResource IconButton}" Content="&#xE76B;" ToolTip="뒤로 (Alt+←)" Margin="0,0,3,0" Click="NavBack_Click"/>
<Button Name="NavForward" Style="{StaticResource IconButton}" Content="&#xE76C;" ToolTip="앞으로 (Alt+→)" Margin="0,0,3,0" Click="NavForward_Click"/>
<Button Name="NavRefresh" Style="{StaticResource IconButton}" Content="&#xE72C;" ToolTip="새로고침 (F5)" Margin="0,0,3,0" Click="NavRefresh_Click"/>
<Button Name="NavHome" Style="{StaticResource IconButton}" Content="&#xE80F;" ToolTip="홈" Click="NavHome_Click"/>
</StackPanel>
<!-- 우측 액션 + 캡션 (Fluent 아이콘 + 툴팁) -->
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal" VerticalAlignment="Center" Margin="10,0,0,0">
<Button Name="BookmarksBtn" Style="{StaticResource IconButton}" Content="&#xE734;" ToolTip="즐겨찾기" Margin="0,0,2,0" Click="ToggleBookmarks"/>
<Button Name="HistoryBtn" Style="{StaticResource IconButton}" Content="&#xE823;" ToolTip="방문 기록" Margin="0,0,2,0" Click="ToggleHistory"/>
<Button Name="TabSearchBtn" Style="{StaticResource IconButton}" Content="&#xE721;" ToolTip="탭 검색 (Ctrl+Shift+A)" Margin="0,0,2,0" Click="ToggleTabSearch"/>
<Button Name="DownloadsBtn" Style="{StaticResource IconButton}" Content="&#xE896;" ToolTip="다운로드 (Ctrl+J)" Margin="0,0,2,0" Click="ToggleDownloads"/>
<Button Name="PlaylistBtn" Style="{StaticResource IconButton}" Content="&#xE8D6;" ToolTip="미디어 재생목록" Margin="0,0,2,0" Click="TogglePlaylistPanel"/>
<Button Style="{StaticResource IconButton}" Content="&#xE8B7;" ToolTip="저장 폴더 열기" Margin="0,0,2,0" Click="OpenFolder_Click"/>
<Button Name="LinkBtn" Style="{StaticResource IconButton}" Content="&#xE71B;" ToolTip="링크로 받기 (YouTube·Instagram·X)" Margin="0,0,2,0" Click="ToggleLink"/>
<Button x:Name="PrivateBtn" Style="{StaticResource IconButton}" Content="&#xE72E;" ToolTip="개인정보 보호 모드(InPrivate)" Margin="0,0,2,0" Click="TogglePrivate_Click"/>
<Button Style="{StaticResource IconButton}" Content="&#xE713;" ToolTip="설정" Margin="0,0,8,0" Click="Settings_Click"/>
<Button Style="{StaticResource PrimaryButton}" Content="이동" ToolTip="주소로 이동 (Enter)" Height="32" Click="Go_Click"/>
<!-- 구분선 (좌우 대칭 여백) -->
<Border Width="1" Background="{StaticResource BorderSubtle}" Margin="10,8"/>
<!-- 윈도우 캡션 컨트롤 (고정폭, 서로 밀착) -->
<Button Style="{StaticResource CaptionButton}" Content="&#xE921;" ToolTip="최소화" Click="Minimize_Click"/>
<Button Name="MaxRestoreBtn" Style="{StaticResource CaptionButton}" Content="&#xE922;" ToolTip="최대화" Click="MaxRestore_Click"/>
<Button Style="{StaticResource CloseButton}" Content="&#xE8BB;" ToolTip="닫기" Click="Close_Click"/>
</StackPanel>
<!-- 주소창 -->
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="8" Height="32" VerticalAlignment="Center">
<TextBox Name="AddressBox" Style="{StaticResource DarkTextBox}"
PreviewKeyDown="AddressBox_PreviewKeyDown" TextChanged="AddressBox_TextChanged"
BorderThickness="0" Background="Transparent"
Padding="14,0" FontSize="13" VerticalContentAlignment="Center"/>
</Border>
</DockPanel>
</Border>
<!-- ===== 북마크바 (T1-6, Ctrl+Shift+B 토글) ===== -->
<Border x:Name="BookmarkBar" Grid.Row="1" Background="{StaticResource PanelBg}"
BorderBrush="{StaticResource BorderSubtle}" BorderThickness="0,0,0,1" Padding="8,3"
Visibility="Collapsed">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
<ItemsControl x:Name="BookmarkBarList" ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Style="{StaticResource FlatButton}" Click="BookmarkBar_Click"
Padding="10,4" Margin="2,1" ToolTip="{Binding Url}">
<TextBlock Text="{Binding Title}" TextTrimming="CharacterEllipsis"
MaxWidth="130" FontSize="12"/>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Border>
<!-- ===== 탭 스트립 (Phase A) ===== -->
<Border x:Name="TabStripRow" Grid.Row="2" Background="{StaticResource PanelBg}"
BorderBrush="{StaticResource BorderSubtle}" BorderThickness="0,0,0,1" Padding="8,4,8,0">
<DockPanel>
<Button x:Name="NewTabBtn" DockPanel.Dock="Right" Style="{StaticResource IconButton}"
Content="&#xE710;" FontSize="13" ToolTip="새 탭 (Ctrl+T)" Click="NewTab_Click"
Margin="4,0,2,3" VerticalAlignment="Center"/>
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Disabled"
VerticalAlignment="Bottom">
<ItemsControl x:Name="TabList">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0,4,0" MinWidth="130" MaxWidth="220">
<Border x:Name="TabBg" CornerRadius="8,8,0,0"
Background="{StaticResource GlassBg}"
BorderBrush="{StaticResource BorderSubtle}" BorderThickness="1,1,1,0"
Padding="10,7,4,7" MouseLeftButtonUp="Tab_Click"
PreviewMouseDown="Tab_PreviewMouseDown"
MouseRightButtonUp="Tab_ContextMenu"
ToolTip="{Binding Url}">
<DockPanel>
<Border DockPanel.Dock="Left" Width="3" CornerRadius="2" Margin="0,0,7,0"
Visibility="{Binding GroupColor, Converter={x:Static feat:StringToBrushConverter.VisibleIf}}">
<Border.Background>
<SolidColorBrush Color="{Binding GroupColor, Converter={x:Static feat:StringToBrushConverter.Conv}}"/>
</Border.Background>
</Border>
<Button DockPanel.Dock="Right" Style="{StaticResource CardActionButton}"
Content="&#xE711;" FontSize="9" Padding="5,3" Margin="4,0,0,0"
Click="TabClose_Click" ToolTip="탭 닫기 (Ctrl+W)"
VerticalAlignment="Center"/>
<TextBlock x:Name="AudioIcon" Text="&#xE767;" Style="{StaticResource FluentIcon}"
FontSize="11" Margin="0,0,6,0" VerticalAlignment="Center"
Visibility="Collapsed" Cursor="Hand"
MouseLeftButtonUp="TabAudio_Click"/>
<TextBlock Text="{Binding Title}" TextTrimming="CharacterEllipsis"
FontSize="12" VerticalAlignment="Center"/>
</DockPanel>
</Border>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="True">
<Setter TargetName="TabBg" Property="Background" Value="{StaticResource CardBg}"/>
<Setter TargetName="TabBg" Property="BorderBrush" Value="{StaticResource AccentFadeBrush}"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsAudioPlaying}" Value="True">
<Setter TargetName="AudioIcon" Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsMuted}" Value="True">
<Setter TargetName="AudioIcon" Property="Text" Value="&#xE74F;"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsPinned}" Value="True">
<Setter TargetName="TabBg" Property="Background" Value="{StaticResource AccentFadeBrush}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
</Border>
<!-- ===== 본문 ===== -->
<Grid Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="SideStripCol" Width="0"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition x:Name="SplitCol" Width="0"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition x:Name="RightCol" Width="420" MinWidth="56" MaxWidth="900"/>
</Grid.ColumnDefinitions>
<!-- T2-5 세로 탭 사이드 호스트 -->
<Border x:Name="TabSideHost" Grid.Column="0" Background="{StaticResource PanelBg}"
BorderBrush="{StaticResource BorderSubtle}" BorderThickness="0,0,1,0"
ClipToBounds="True" MinWidth="170" MaxWidth="330"/>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" ClipToBounds="True" Background="Black">
<Grid x:Name="TabHost" Background="Black"/>
</Border>
<!-- 페이지 내 검색 바 (T1-3): WebView2(airspace) 아래에 도킹 -->
<Border x:Name="FindBar" Grid.Row="1" Visibility="Collapsed"
Background="{StaticResource PanelBg}" BorderBrush="{StaticResource BorderSubtle}"
BorderThickness="0,1,0,0" Padding="12,6">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<CheckBox x:Name="FindCaseBox" Style="{StaticResource DarkCheckBox}" Content="Aa"
ToolTip="대소문자 구분" Margin="0,0,8,0" VerticalAlignment="Center"
Checked="FindOption_Changed" Unchecked="FindOption_Changed"/>
<CheckBox x:Name="FindWordBox" Style="{StaticResource DarkCheckBox}" Content="단어"
ToolTip="전체 단어 일치" Margin="0,0,10,0" VerticalAlignment="Center"
Checked="FindOption_Changed" Unchecked="FindOption_Changed"/>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="7" Width="230">
<TextBox x:Name="FindBox" Style="{StaticResource DarkTextBox}" BorderThickness="0"
Background="Transparent" Padding="10,4" FontSize="12.5"
VerticalContentAlignment="Center"
TextChanged="FindBox_TextChanged" PreviewKeyDown="FindBox_PreviewKeyDown"/>
</Border>
<Button Style="{StaticResource IconButton}" Content="&#xE74A;" ToolTip="이전 매치 (Shift+F3)"
Margin="6,0,0,0" Click="FindPrev_Click"/>
<Button Style="{StaticResource IconButton}" Content="&#xE74B;" ToolTip="다음 매치 (F3)"
Margin="2,0,0,0" Click="FindNext_Click"/>
<TextBlock x:Name="FindStatus" Text="" Foreground="{StaticResource TextMuted}" FontSize="11.5"
VerticalAlignment="Center" Margin="10,0,4,0" MinWidth="52"/>
<Button Style="{StaticResource IconButton}" Content="&#xE711;" ToolTip="닫기 (Esc)"
Click="FindClose_Click"/>
</StackPanel>
</Border>
</Grid>
<!-- 리사이즈 핸들 (펼침 상태에서만 노출). 드래그로 우측 패널 폭 변경. -->
<!-- T2-3 분할 화면: 드래그 스플리터 + 우측 탭 호스트 -->
<GridSplitter x:Name="SplitSplitter" Grid.Column="2" Width="7"
HorizontalAlignment="Center" VerticalAlignment="Stretch"
ResizeBehavior="PreviousAndNext" ResizeDirection="Columns"
Background="Transparent" Cursor="SizeWE" Visibility="Collapsed"/>
<Border x:Name="SplitRightHost" Grid.Column="3" ClipToBounds="True" Background="Black"
Visibility="Collapsed"/>
<GridSplitter x:Name="RightSplitter" Grid.Column="4" Width="7"
HorizontalAlignment="Center" VerticalAlignment="Stretch"
ResizeBehavior="PreviousAndNext" ResizeDirection="Columns"
Background="Transparent" Cursor="SizeWE"
DragCompleted="RightSplitter_DragCompleted">
<GridSplitter.Template>
<ControlTemplate TargetType="GridSplitter">
<Border x:Name="handle" Background="Transparent">
<Rectangle Width="1" HorizontalAlignment="Center" Fill="{StaticResource BorderSubtle}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="handle" Property="Background" Value="{StaticResource AccentFadeBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</GridSplitter.Template>
</GridSplitter>
<!-- 범용 우측 패널: 헤더(토글 버튼, 항상 노출) + 본문(펼침 시). 접기/펼치기·폭·상태 저장. -->
<Border Grid.Column="5" Background="{StaticResource PanelBg}"
BorderBrush="{StaticResource BorderSubtle}" BorderThickness="1,0,0,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0" Margin="10,12,10,8" LastChildFill="True">
<Button x:Name="PanelToggle" DockPanel.Dock="Right" Style="{StaticResource IconButton}"
Click="PanelToggle_Click" ToolTip="패널 접기"
VerticalAlignment="Center" Margin="4,0,0,0" Content="&#xE76C;"/>
<Border x:Name="PanelCountBadge" DockPanel.Dock="Right" Background="{StaticResource GlassBg}"
CornerRadius="9" Padding="9,2" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,8,0">
<TextBlock Text="{Binding Items.Count}" Foreground="{StaticResource TextSecondary}" FontSize="11"/>
</Border>
<TextBlock x:Name="PanelTitle" Text="다운로드" Foreground="{StaticResource TextPrimary}"
FontWeight="SemiBold" FontSize="13.5" VerticalAlignment="Center"/>
</DockPanel>
<Grid Grid.Row="1" x:Name="PanelBody">
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Center" Margin="0,60,0,0"
Visibility="{Binding Items.Count, Converter={StaticResource InverseCountToVisibility}}">
<Border Width="54" Height="54" CornerRadius="14" Background="{StaticResource GlassBg}"
BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" HorizontalAlignment="Center">
<TextBlock Text="&#xE8B2;" Style="{StaticResource FluentIcon}" FontSize="24" Foreground="{StaticResource TextMuted}"/>
</Border>
<TextBlock Text="영상을 재생하면 여기에 나타납니다" Foreground="{StaticResource TextSecondary}"
FontSize="13" FontWeight="Medium" HorizontalAlignment="Center" Margin="0,14,0,2"/>
<TextBlock Text="탐지 즉시 자동으로 목록에 추가돼요" Foreground="{StaticResource TextMuted}"
FontSize="11.5" HorizontalAlignment="Center"/>
</StackPanel>
<ScrollViewer VerticalScrollBarVisibility="Auto" Padding="16,2,16,16">
<ItemsControl ItemsSource="{Binding Items}"/>
</ScrollViewer>
</Grid>
</Grid>
</Border>
</Grid>
<!-- ===== 상태 표시줄 ===== -->
<Border x:Name="StatusBar" Grid.Row="4" Background="{StaticResource PanelBg}"
BorderBrush="{StaticResource BorderSubtle}" BorderThickness="0,1,0,0" Padding="16,5">
<TextBlock Name="StatusText" Foreground="{StaticResource TextMuted}" FontSize="11"
TextTrimming="CharacterEllipsis" Text="준비"/>
</Border>
<!-- ===== 즐겨찾기 플라이아웃 ===== -->
<Popup Name="BookmarksPopup" PlacementTarget="{Binding ElementName=BookmarksBtn}"
Placement="Bottom" HorizontalOffset="-10" VerticalOffset="6"
StaysOpen="False" AllowsTransparency="True" PopupAnimation="Fade">
<Border Background="{StaticResource CardBg}" BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="12" Padding="8" Width="320" MaxHeight="460">
<StackPanel>
<DockPanel Margin="6,4,6,6">
<TextBlock Text="즐겨찾기" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold" VerticalAlignment="Center"/>
<Button DockPanel.Dock="Right" Style="{StaticResource CardActionButton}" Content="+ 현재 페이지 추가" Click="AddBookmark_Click" HorizontalAlignment="Right"/>
</DockPanel>
<Border Background="{StaticResource BorderSubtle}" Height="1" Margin="0,0,0,4"/>
<ItemsControl Name="BookmarksList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DockPanel Margin="0,1">
<Button DockPanel.Dock="Right" Style="{StaticResource CardActionButton}" Content="✕"
Click="RemoveBookmark_Click" Padding="8,5" Margin="6,0,0,0" VerticalAlignment="Center"/>
<Button Style="{StaticResource FlatButton}" Click="OpenBookmark_Click" HorizontalAlignment="Stretch">
<StackPanel>
<TextBlock Text="{Binding Title}" TextTrimming="CharacterEllipsis" FontSize="12.5" FontWeight="Medium"/>
<TextBlock Text="{Binding Url}" Foreground="{StaticResource TextMuted}" FontSize="10.5" TextTrimming="CharacterEllipsis"/>
</StackPanel>
</Button>
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</Popup>
<!-- ===== 히스토리 플라이아웃 ===== -->
<Popup Name="HistoryPopup" PlacementTarget="{Binding ElementName=HistoryBtn}"
Placement="Bottom" HorizontalOffset="-10" VerticalOffset="6"
StaysOpen="False" AllowsTransparency="True" PopupAnimation="Fade">
<Border Background="{StaticResource CardBg}" BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="12" Padding="8" Width="340" MaxHeight="480">
<StackPanel>
<DockPanel Margin="6,4,6,6">
<TextBlock Text="방문 기록" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold" VerticalAlignment="Center"/>
<Button DockPanel.Dock="Right" Style="{StaticResource CardActionButton}" Content="🗑 전체 삭제" Click="ClearHistory_Click" HorizontalAlignment="Right"/>
</DockPanel>
<Border Background="{StaticResource BorderSubtle}" Height="1" Margin="0,0,0,4"/>
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="400">
<ItemsControl Name="HistoryList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Style="{StaticResource FlatButton}" Click="OpenHistory_Click" HorizontalAlignment="Stretch" Margin="0,1">
<StackPanel>
<DockPanel>
<TextBlock DockPanel.Dock="Right" Text="{Binding VisitedAt, StringFormat=HH:mm}" Foreground="{StaticResource TextMuted}" FontSize="10.5" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Title}" TextTrimming="CharacterEllipsis" FontSize="12.5" FontWeight="Medium"/>
</DockPanel>
<TextBlock Text="{Binding Url}" Foreground="{StaticResource TextMuted}" FontSize="10.5" TextTrimming="CharacterEllipsis"/>
</StackPanel>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</StackPanel>
</Border>
</Popup>
<!-- ===== 주소창 자동완성 제안 ===== -->
<Popup Name="AddressPopup" PlacementTarget="{Binding ElementName=AddressBox}"
Placement="Bottom" StaysOpen="False" AllowsTransparency="True" PopupAnimation="Fade"
Width="560" MaxHeight="380">
<Border Background="{StaticResource CardBg}" BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="10" Padding="4">
<ListBox Name="AddressSuggestions" Style="{StaticResource SuggestList}"
ItemContainerStyle="{StaticResource SuggestItem}"
PreviewMouseLeftButtonUp="AddressSuggestion_Click">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Title}" TextTrimming="CharacterEllipsis" FontSize="12.5" FontWeight="Medium"/>
<TextBlock Text="{Binding Url}" Foreground="{StaticResource TextMuted}" FontSize="10.5" TextTrimming="CharacterEllipsis"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
</Popup>
<!-- ===== 다운로드 플라이아웃 (T1-5) ===== -->
<Popup Name="DownloadsPopup" PlacementTarget="{Binding ElementName=DownloadsBtn}"
Placement="Bottom" HorizontalOffset="-10" VerticalOffset="6"
StaysOpen="False" AllowsTransparency="True" PopupAnimation="Fade">
<Border Background="{StaticResource CardBg}" BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="12" Padding="10" Width="420" MaxHeight="460">
<StackPanel>
<DockPanel Margin="6,2,6,8">
<TextBlock Text="다운로드" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold" VerticalAlignment="Center"/>
<Button DockPanel.Dock="Right" Style="{StaticResource CardActionButton}" Content="완료 항목 지우기"
Click="DownloadsClear_Click" HorizontalAlignment="Right"/>
</DockPanel>
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="380">
<ItemsControl Name="DownloadsList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderSubtle}"
BorderThickness="1" CornerRadius="8" Padding="10" Margin="0,0,0,8">
<StackPanel>
<DockPanel>
<TextBlock DockPanel.Dock="Right" Text="{Binding SpeedText}" Foreground="{StaticResource TextMuted}"
FontSize="11" VerticalAlignment="Center" Margin="8,0,0,0"/>
<TextBlock Text="{Binding FileName}" Foreground="{StaticResource TextPrimary}"
FontSize="12.5" FontWeight="Medium" TextTrimming="CharacterEllipsis"/>
</DockPanel>
<ProgressBar Value="{Binding Percent}" Maximum="100" Height="6" Margin="0,7,0,6"
Style="{StaticResource AccentProgressBar}"/>
<DockPanel>
<TextBlock Text="{Binding State}" Foreground="{StaticResource TextSecondary}" FontSize="11" VerticalAlignment="Center"/>
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal">
<Button Style="{StaticResource CardActionButton}" Content="일시정지" Click="DlPause_Click" Margin="0,0,5,0"/>
<Button Style="{StaticResource CardActionButton}" Content="재개" Click="DlResume_Click" Margin="0,0,5,0"/>
<Button Style="{StaticResource CardActionButton}" Content="취소" Click="DlCancel_Click"/>
</StackPanel>
</DockPanel>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<TextBlock Text="페이지 내 파일 다운로드가 여기 표시됩니다" Foreground="{StaticResource TextMuted}"
FontSize="11" HorizontalAlignment="Center" Margin="0,4,0,0"
x:Name="DownloadsEmptyHint"/>
</StackPanel>
</Border>
</Popup>
<!-- ===== 탭 검색 팝업 (T2-8, Ctrl+Shift+A) ===== -->
<Popup Name="TabSearchPopup" PlacementTarget="{Binding ElementName=AddressBox}"
Placement="Center" StaysOpen="False" AllowsTransparency="True" PopupAnimation="Fade"
Width="520">
<Border Background="{StaticResource CardBg}" BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="12" Padding="10">
<StackPanel>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="8" Margin="2,0,2,8">
<TextBox Name="TabSearchBox" Style="{StaticResource DarkTextBox}" BorderThickness="0"
Background="Transparent" Padding="12,9" FontSize="13"
TextChanged="TabSearchBox_TextChanged" PreviewKeyDown="TabSearchBox_PreviewKeyDown"/>
</Border>
<ListBox Name="TabSearchResults" Style="{StaticResource SuggestList}"
ItemContainerStyle="{StaticResource SuggestItem}" MaxHeight="320"
PreviewMouseLeftButtonUp="TabSearchResult_Click">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<DockPanel>
<TextBlock DockPanel.Dock="Right" Text="{Binding IsClosed, Converter={x:Static feat:BoolToClosedConverter.Instance}}"
Foreground="{StaticResource TextMuted}" FontSize="10.5" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Title}" TextTrimming="CharacterEllipsis" FontSize="12.5" FontWeight="Medium"/>
</DockPanel>
<TextBlock Text="{Binding Url}" Foreground="{StaticResource TextMuted}" FontSize="10.5" TextTrimming="CharacterEllipsis"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Border>
</Popup>
<!-- ===== 명령 팔레트 (T2-1, Ctrl+K) ===== -->
<Popup Name="PalettePopup" PlacementTarget="{Binding ElementName=AddressBox}"
Placement="Center" StaysOpen="False" AllowsTransparency="True" PopupAnimation="Fade"
Width="560">
<Border Background="{StaticResource CardBg}" BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="12" Padding="10">
<StackPanel>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="8" Margin="2,0,2,8">
<TextBox Name="PaletteBox" Style="{StaticResource DarkTextBox}" BorderThickness="0"
Background="Transparent" Padding="12,10" FontSize="13.5"
TextChanged="PaletteBox_TextChanged" PreviewKeyDown="PaletteBox_PreviewKeyDown"/>
</Border>
<ListBox Name="PaletteResults" Style="{StaticResource SuggestList}"
ItemContainerStyle="{StaticResource SuggestItem}" MaxHeight="360"
PreviewMouseLeftButtonUp="PaletteResult_Click">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" TextTrimming="CharacterEllipsis"
FontSize="12.5" Padding="4,2"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Border>
</Popup>
<!-- ===== 미디어 재생목록 플라이아웃 (T2-10) ===== -->
<Popup Name="PlaylistPopup" PlacementTarget="{Binding ElementName=PlaylistBtn}"
Placement="Bottom" HorizontalOffset="-10" VerticalOffset="6"
StaysOpen="False" AllowsTransparency="True" PopupAnimation="Fade">
<Border Background="{StaticResource CardBg}" BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="12" Padding="10" Width="440" MaxHeight="470">
<StackPanel>
<DockPanel Margin="6,2,6,8">
<TextBlock Text="미디어 재생목록" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold" VerticalAlignment="Center"/>
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Style="{StaticResource CardActionButton}" Content="▶ 재생" Click="PlaylistPlayAll_Click" Margin="0,0,5,0"/>
<Button Style="{StaticResource CardActionButton}" Content="비우기" Click="PlaylistClear_Click"/>
</StackPanel>
</DockPanel>
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="380">
<ItemsControl Name="PlaylistList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderSubtle}"
BorderThickness="1" CornerRadius="8" Padding="10" Margin="0,0,0,7">
<DockPanel>
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal">
<Button Style="{StaticResource CardActionButton}" Content="▶" Click="PlaylistPlay_Click" Margin="0,0,5,0"/>
<Button Style="{StaticResource CardActionButton}" Content="✕" Click="PlaylistRemove_Click"/>
</StackPanel>
<StackPanel>
<TextBlock Text="{Binding Title}" Foreground="{StaticResource TextPrimary}" FontSize="12.5"
FontWeight="Medium" TextTrimming="CharacterEllipsis"/>
<TextBlock Foreground="{StaticResource TextMuted}" FontSize="10.5" TextTrimming="CharacterEllipsis">
<Run Text="{Binding Kind}"/><Run Text=" · "/><Run Text="{Binding AddedAt, StringFormat=MM-dd HH:mm}"/>
</TextBlock>
</StackPanel>
</DockPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<TextBlock x:Name="PlaylistEmptyHint" Text="영상을 재생하면 자동으로 쌓입니다" Foreground="{StaticResource TextMuted}"
FontSize="11" HorizontalAlignment="Center" Margin="0,4,0,0"/>
</StackPanel>
</Border>
</Popup>
<!-- ===== 링크로 받기 플라이아웃 (YouTube/Instagram/X URL 붙여넣기) ===== -->
<Popup Name="LinkPopup" PlacementTarget="{Binding ElementName=LinkBtn}"
Placement="Bottom" HorizontalOffset="-10" VerticalOffset="6"
StaysOpen="False" AllowsTransparency="True" PopupAnimation="Fade">
<Border Background="{StaticResource CardBg}" BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="12" Padding="10" Width="380">
<StackPanel>
<TextBlock Text="링크로 받기" Foreground="{StaticResource TextPrimary}" FontWeight="SemiBold" Margin="6,2,6,4"/>
<TextBlock Text="YouTube·Instagram·X 등 영상 링크를 붙여넣고 받기를 누르세요" Foreground="{StaticResource TextMuted}" FontSize="11" Margin="6,0,6,10" TextWrapping="Wrap"/>
<DockPanel>
<Button DockPanel.Dock="Right" Style="{StaticResource PrimaryButton}" Content="받기" Margin="8,0,0,0" Click="LinkDownload_Click"/>
<Border Background="{StaticResource GlassBg}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="8">
<TextBox Name="LinkBox" Style="{StaticResource DarkTextBox}" BorderThickness="0" Background="Transparent"
Padding="12,8" PreviewKeyDown="LinkBox_PreviewKeyDown"/>
</Border>
</DockPanel>
</StackPanel>
</Border>
</Popup>
</Grid>
</Window>