165 lines
7.5 KiB
C#
165 lines
7.5 KiB
C#
using System.Runtime.InteropServices;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Interop;
|
|
using Microsoft.Win32;
|
|
using VideoDownloader.Core.Config;
|
|
using VideoDownloader.Core.Social;
|
|
|
|
namespace VideoDownloader.App;
|
|
|
|
public partial class SettingsWindow : Window
|
|
{
|
|
public AppConfig Config { get; }
|
|
private readonly string _origTheme;
|
|
private readonly Func<Task>? _clearBrowsingData;
|
|
public bool ThemeChanged { get; private set; }
|
|
|
|
public SettingsWindow(AppConfig config, Func<Task>? clearBrowsingData = null)
|
|
{
|
|
InitializeComponent();
|
|
Config = config;
|
|
_origTheme = config.Theme;
|
|
_clearBrowsingData = clearBrowsingData;
|
|
|
|
FolderBox.Text = config.OutputFolder;
|
|
HomeBox.Text = config.HomeUrl;
|
|
ConcurrencyBox.Text = config.Concurrency.ToString();
|
|
MinSizeBox.Text = config.MinSizeMB.ToString();
|
|
MaxConcurrentBox.Text = config.MaxConcurrentDownloads.ToString();
|
|
ThemeLightBox.IsChecked = config.Theme.Equals("light", StringComparison.OrdinalIgnoreCase);
|
|
FfmpegBox.Text = config.FfmpegPath ?? "";
|
|
|
|
FmtHls.IsChecked = config.EnabledFormats.Contains("hls");
|
|
FmtDash.IsChecked = config.EnabledFormats.Contains("dash");
|
|
FmtMp4.IsChecked = config.EnabledFormats.Contains("mp4");
|
|
FmtWebM.IsChecked = config.EnabledFormats.Contains("webm");
|
|
FmtMkv.IsChecked = config.EnabledFormats.Contains("mkv");
|
|
FmtM4v.IsChecked = config.EnabledFormats.Contains("m4v");
|
|
FmtMov.IsChecked = config.EnabledFormats.Contains("mov");
|
|
FmtAvi.IsChecked = config.EnabledFormats.Contains("avi");
|
|
FmtAudio.IsChecked = config.EnabledFormats.Contains("audio");
|
|
|
|
YtDlpBox.Text = config.YtDlpPath ?? "";
|
|
UseCookiesBox.IsChecked = config.UseCookiesForSocial;
|
|
AutoInstallBox.IsChecked = config.AutoInstallYtDlp;
|
|
AutoUpdateBox.IsChecked = config.AutoUpdateYtDlp;
|
|
AutoInstallDenoBox.IsChecked = config.AutoInstallDeno;
|
|
DefaultQualityBox.SelectedValue = config.DefaultSocialQuality;
|
|
if (DefaultQualityBox.SelectedIndex < 0) DefaultQualityBox.SelectedIndex = 0;
|
|
YoutubeClientsBox.Text = config.YoutubePlayerClients ?? "";
|
|
|
|
ProfilePathBox.Text = MainWindow.ProfileFolder;
|
|
ProfileModeText.Text = config.PrivateMode
|
|
? "개인정보 보호 모드(InPrivate) — 데이터를 저장하지 않습니다"
|
|
: "일반 모드 — 쿠키·세션·localStorage 를 프로필에 보존합니다";
|
|
}
|
|
|
|
private void BrowseFolder(object sender, RoutedEventArgs e)
|
|
{
|
|
var dlg = new OpenFolderDialog();
|
|
if (Directory.Exists(FolderBox.Text)) dlg.InitialDirectory = FolderBox.Text;
|
|
if (dlg.ShowDialog() == true)
|
|
FolderBox.Text = dlg.FolderName;
|
|
}
|
|
|
|
private void BrowseFfmpeg(object sender, RoutedEventArgs e)
|
|
{
|
|
var dlg = new OpenFileDialog { Filter = "ffmpeg|ffmpeg.exe|실행 파일|*.exe|모든 파일|*.*" };
|
|
if (dlg.ShowDialog() == true)
|
|
FfmpegBox.Text = dlg.FileName;
|
|
}
|
|
|
|
private void BrowseYtDlp(object sender, RoutedEventArgs e)
|
|
{
|
|
var dlg = new OpenFileDialog { Filter = "yt-dlp|yt-dlp.exe|실행 파일|*.exe|모든 파일|*.*" };
|
|
if (dlg.ShowDialog() == true)
|
|
YtDlpBox.Text = dlg.FileName;
|
|
}
|
|
|
|
private async void ReinstallYtDlp_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var btn = sender as Button;
|
|
if (btn != null) btn.IsEnabled = false;
|
|
try
|
|
{
|
|
var path = await YtDlpRunner.DownloadAsync(Config, null, CancellationToken.None);
|
|
MessageBox.Show(path != null ? $"yt-dlp 설치 완료:\n{path}" : "yt-dlp 다운로드에 실패했습니다. 네트워크를 확인하세요.",
|
|
"yt-dlp", MessageBoxButton.OK, path != null ? MessageBoxImage.Information : MessageBoxImage.Warning);
|
|
if (path != null) YtDlpBox.Text = "";
|
|
}
|
|
finally { if (btn != null) btn.IsEnabled = true; }
|
|
}
|
|
|
|
private async void ClearData_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (_clearBrowsingData == null) return;
|
|
if (MessageBox.Show("쿠키·localStorage·캐시 등 브라우저 데이터를 삭제합니다.\n로그인이 풀릴 수 있습니다. 계속할까요?",
|
|
"데이터 삭제", MessageBoxButton.OKCancel, MessageBoxImage.Warning) != MessageBoxResult.OK) return;
|
|
var btn = sender as Button;
|
|
if (btn != null) btn.IsEnabled = false;
|
|
try { await _clearBrowsingData(); }
|
|
finally { if (btn != null) btn.IsEnabled = true; }
|
|
}
|
|
|
|
private void Ok_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
Config.OutputFolder = FolderBox.Text?.Trim() ?? "";
|
|
Config.HomeUrl = string.IsNullOrWhiteSpace(HomeBox.Text) ? "https://www.google.com" : HomeBox.Text.Trim();
|
|
if (int.TryParse(ConcurrencyBox.Text, out var c)) Config.Concurrency = Math.Max(1, c);
|
|
if (long.TryParse(MinSizeBox.Text, out var m) && m >= 0) Config.MinSizeMB = m;
|
|
Config.FfmpegPath = string.IsNullOrWhiteSpace(FfmpegBox.Text) ? null : FfmpegBox.Text.Trim();
|
|
|
|
Config.Theme = ThemeLightBox.IsChecked == true ? "light" : "dark";
|
|
if (int.TryParse(MaxConcurrentBox.Text, out var mc)) Config.MaxConcurrentDownloads = Math.Max(1, mc);
|
|
ThemeChanged = !Config.Theme.Equals(_origTheme, StringComparison.OrdinalIgnoreCase);
|
|
|
|
var fmts = new List<string>();
|
|
if (FmtHls.IsChecked == true) fmts.Add("hls");
|
|
if (FmtDash.IsChecked == true) fmts.Add("dash");
|
|
if (FmtMp4.IsChecked == true) fmts.Add("mp4");
|
|
if (FmtWebM.IsChecked == true) fmts.Add("webm");
|
|
if (FmtMkv.IsChecked == true) fmts.Add("mkv");
|
|
if (FmtM4v.IsChecked == true) fmts.Add("m4v");
|
|
if (FmtMov.IsChecked == true) fmts.Add("mov");
|
|
if (FmtAvi.IsChecked == true) fmts.Add("avi");
|
|
if (FmtAudio.IsChecked == true) fmts.Add("audio");
|
|
Config.EnabledFormats = fmts;
|
|
|
|
Config.YtDlpPath = string.IsNullOrWhiteSpace(YtDlpBox.Text) ? null : YtDlpBox.Text.Trim();
|
|
Config.UseCookiesForSocial = UseCookiesBox.IsChecked == true;
|
|
Config.AutoInstallYtDlp = AutoInstallBox.IsChecked == true;
|
|
Config.AutoUpdateYtDlp = AutoUpdateBox.IsChecked == true;
|
|
Config.AutoInstallDeno = AutoInstallDenoBox.IsChecked == true;
|
|
Config.DefaultSocialQuality = (DefaultQualityBox.SelectedValue as string) ?? "best";
|
|
Config.YoutubePlayerClients = string.IsNullOrWhiteSpace(YoutubeClientsBox.Text) ? null : YoutubeClientsBox.Text.Trim();
|
|
|
|
DialogResult = true;
|
|
}
|
|
|
|
// 보더리스: Win11 어두운 테두리 + 둥근 모서리
|
|
protected override void OnSourceInitialized(EventArgs e)
|
|
{
|
|
base.OnSourceInitialized(e);
|
|
try
|
|
{
|
|
var hwnd = new WindowInteropHelper(this).Handle;
|
|
int dark = App.IsLightTheme ? 0 : 1; // DWMWA_USE_IMMERSIVE_DARK_MODE (라이트 테마면 밝게)
|
|
DwmSetWindowAttribute(hwnd, 20, ref dark, sizeof(int));
|
|
int round = 2; // DWMWCP_ROUND
|
|
DwmSetWindowAttribute(hwnd, 33, ref round, sizeof(int));
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private void TitleBar_MouseDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
if (e.LeftButton == MouseButtonState.Pressed) { try { DragMove(); } catch { } }
|
|
}
|
|
|
|
private void Close_Click(object sender, RoutedEventArgs e) => Close();
|
|
|
|
[DllImport("dwmapi.dll")]
|
|
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attribute, ref int pvAttribute, int cbAttribute);
|
|
}
|