Phase D (T2-10): media playlist - auto-collect detected media, flyout management, player window (native+hls.js+dash.js bundles), persistence, auto-next (101 tests GREEN)

This commit is contained in:
Yun Chan 2026-08-15 15:25:10 +09:00
parent 406957088f
commit 40c1b39b70
8 changed files with 491 additions and 0 deletions

View file

@ -191,6 +191,7 @@
<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"/>
@ -633,6 +634,50 @@
</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"