releases/VideoDownloader.Core/Config/AppConfig.cs

253 lines
12 KiB
C#

namespace VideoDownloader.Core.Config;
/// <summary>앱 설정 (JSON 직렬화). %AppData%/VideoDownloader/config.json 에 저장.</summary>
public class AppConfig
{
public string OutputFolder { get; set; } = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyVideos), "VideoDownloader");
/// <summary>홈 버튼이 이동할 URL</summary>
public string HomeUrl { get; set; } = "https://www.google.com";
public int Concurrency { get; set; } = 8;
public int Retries { get; set; } = 6;
/// <summary>동시에 실행할 다운로드(항목) 수 상한. 세그먼트 단위 Concurrency 와 별개.</summary>
public int MaxConcurrentDownloads { get; set; } = 3;
/// <summary>감지/다운로드에 반응할 형식 키: hls/dash/mp4/webm/mkv/m4v/mov/avi/audio</summary>
public List<string> EnabledFormats { get; set; } = new()
{ "hls", "dash", "mp4", "webm", "mkv", "m4v", "mov", "avi", "audio" };
/// <summary>직링크 감지 최소 크기(MB). 이보다 작으면(포스터 등) 무시.</summary>
public long MinSizeMB { get; set; } = 2;
/// <summary>null 이면 시스템 PATH 의 ffmpeg 사용</summary>
public string? FfmpegPath { get; set; }
/// <summary>yt-dlp 실행 파일 경로(null → 번들/PATH/자동다운로드). 소셜 영상(YouTube·Instagram·X) 다운로드용.</summary>
public string? YtDlpPath { get; set; }
/// <summary>소셜 다운로드 시 로그인 콘텐츠(인스타·X·멤버 영상 등) 를 위해 브라우저 쿠키를 yt-dlp 에 전달.</summary>
public bool UseCookiesForSocial { get; set; } = true;
/// <summary>yt-dlp 가 없으면 %AppData%/VideoDownloader/tools 로 자동 다운로드.</summary>
public bool AutoInstallYtDlp { get; set; } = true;
/// <summary>YouTube 안티봇 실패(n 챌린지/PO 토큰/서명 누락 등) 감지 시 yt-dlp 를 최신 버전으로 갱신해 1회 재시도.
/// YouTube 가 난독화를 바꿀 때 yt-dlp 는 보통 몇 시간~며칠 내 대응 릴리스를 내보내므로, 최신화만으로 대부분 복구됨.</summary>
public bool AutoUpdateYtDlp { get; set; } = true;
/// <summary>Deno(JS 런타임) 실행 파일 경로(null → 번들/PATH/자동다운로드). yt-dlp 의 EJS(n 챌린지 해석) 실행에 필요.</summary>
public string? DenoPath { get; set; }
/// <summary>Deno 가 없으면 %AppData%/VideoDownloader/tools 로 자동 다운로드. YouTube n 챌린지(EJS) 해석에 필수.</summary>
public bool AutoInstallDeno { get; set; } = true;
/// <summary>소셜 카드의 기본 화질 프리셋 키: best/1080/720/480/360/audio.</summary>
public string DefaultSocialQuality { get; set; } = "best";
/// <summary>YouTube player_client 오버라이드(예: "tv,android_vr,web"). null/빈 → yt-dlp 공식 기본값 사용(권장).
/// 2026년 기준 android/ios 는 GVS/Player PO 토큰이 필요하고 쿠키를 지원하지 않으며, web_sns 는
/// yt-dlp 에 존재하지 않는 클라이언트라 비워두는 것이 가장 안정적임.</summary>
public string? YoutubePlayerClients { get; set; }
public string UserAgent { get; set; } =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " +
"(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36";
/// <summary>테마: "dark" (기본) 또는 "light".</summary>
public string Theme { get; set; } = "dark";
/// <summary>우측 패널 펼침 폭(px). 접기/펼치기 + 드래그 리사이즈 후 저장.</summary>
public double RightPanelWidth { get; set; } = 420;
/// <summary>우측 패널 접힘 여부.</summary>
public bool RightPanelCollapsed { get; set; } = false;
/// <summary>개인정보 보호(InPrivate) 모드: 쿠키·세션·localStorage 를 디스크에 저장하지 않는다. 적용 시 앱 재시작.</summary>
public bool PrivateMode { get; set; } = false;
/// <summary>주소창 기본 검색 엔진(SearchEngines.Presets 의 Name). 검색어 입력 시 이 엔진으로 검색.</summary>
public string SearchEngine { get; set; } = "Google";
/// <summary>종료 시 탭을 저장하고 다음 시작에 복원(T1-10 세션 복원).</summary>
public bool RestoreSession { get; set; } = true;
/// <summary>M0 원격 접근(모바일 연동) 서버 켜기. 토큰은 자동 생성/저장.</summary>
public bool RemoteAccessEnabled { get; set; } = false;
public string? RemoteAccessToken { get; set; }
/// <summary>업데이트 확인 대상 GitHub 저장소("owner/repo") — DEPLOYMENT_PLAN §6 v1. 비면 확인 안 함.</summary>
public string UpdateRepo { get; set; } = "";
// ==================== UI 복잡 버전 (docs/UI_USECASES.md) ====================
// ---- §A 테마 ----
/// <summary>사용자 지정 강조색(#RRGGBB). null/빈이면 테마 기본 보라.</summary>
public string? AccentColor { get; set; }
/// <summary>사용자 테마 파일(.xaml 리소스사전) 경로. 설정에 있으면 우선 적용.</summary>
public string? CustomThemePath { get; set; }
// ---- §B 타이포그래피 ----
/// <summary>UI 기본 폰트(빈 문자열이면 기본 스택 Segoe UI+맑은고딕).</summary>
public string UiFontFamily { get; set; } = "";
/// <summary>UI 기본 폰트 크기(pt 단위가 아닌 WPF Device Independent px).</summary>
public double UiFontSize { get; set; } = 13;
/// <summary>한국어 폴백 폰트(기본 '맑은 고딕').</summary>
public string UiFontKoreanFallback { get; set; } = "Malgun Gothic";
// ---- §C 레이아웃·밀도·창 상태 ----
/// <summary>정보 밀도: compact / normal / comfortable.</summary>
public string UiDensity { get; set; } = "normal";
/// <summary>T3-13 컴팩트 모드(크롬 숨김) 시작 시 복원.</summary>
public bool CompactMode { get; set; } = false;
/// <summary>세로 탭을 기본 레이아웃으로 시작.</summary>
public bool VerticalTabsDefault { get; set; } = false;
/// <summary>분할 화면(스플릿) 패널 비율(0~1). 재시작 후 재현.</summary>
public double SplitViewRatio { get; set; } = 0.5;
/// <summary>창 위치·크기 "Left,Top,Width,Height". 화면 밤새 좌표는 무시됨.</summary>
public string? WindowBounds { get; set; }
/// <summary>종료 시 최대화 상태였는지.</summary>
public bool WindowMaximized { get; set; } = false;
/// <summary>사용 중인 상태바는 자동으로 숨김.</summary>
public bool StatusBarAutoHide { get; set; } = false;
/// <summary>툴바에 남길 버튼 키 목록(빈 목록=전부 표시). 예: back,forward,bookmarks,history,downloads</summary>
public List<string> ToolbarButtons { get; set; } = new();
/// <summary>북마크바 표시 여부(세션 간 유지).</summary>
public bool BookmarkBarVisible { get; set; } = false;
/// <summary>탭 스트립 위치: top / bottom / left.</summary>
public string TabStripPosition { get; set; } = "top";
/// <summary>우측 패널 최소 폭(px).</summary>
public double RightPanelMinWidth { get; set; } = 280;
/// <summary>움직임 민감 사용자용 애니메이션 축소.</summary>
public bool ReduceMotion { get; set; } = false;
/// <summary>컴팩트 모드 엣지 호버 반응 지연(ms).</summary>
public int EdgeRevealDelayMs { get; set; } = 200;
/// <summary>UI 전체 배율(레이아웃 루트 ScaleTransform, 0.5~2.0).</summary>
public double UiScale { get; set; } = 1.0;
/// <summary>종료 시 전체화면이었는지.</summary>
public bool FullScreen { get; set; } = false;
// ---- §D 탭 ----
/// <summary>여러 탭을 한 번에 닫을 때 확인 받기.</summary>
public bool ConfirmCloseMultipleTabs { get; set; } = true;
/// <summary>탭 스트립에서 휠로 탭 전환.</summary>
public bool TabWheelSwitch { get; set; } = true;
/// <summary>탭 최대 개수(0=제한 없음).</summary>
public int MaxTabs { get; set; } = 0;
/// <summary>세션 복원 시 탭을 잠자기 상태로만 복원(빠른 시작).</summary>
public bool RestoreTabsSuspended { get; set; } = false;
/// <summary>작업공간 표시 이름(인덱스 순).</summary>
public List<string> WorkspaceNames { get; set; } = new() { "작업", "개인", "학습" };
/// <summary>탭 제목 두 줄 표시.</summary>
public bool TabTitleMultiline { get; set; } = false;
// ---- §E 다운로드 ----
/// <summary>다운로드 목록 정렬: newest / largest / progress / title.</summary>
public string DownloadSortOrder { get; set; } = "newest";
/// <summary>완료 항목을 n초 후 목록에서 자동 제거(0=자동 치움 안 함).</summary>
public bool AutoClearCompleted { get; set; } = false;
/// <summary>다운로드 완료 알림 소리.</summary>
public bool NotifySound { get; set; } = true;
/// <summary>다운로드 완료 시 저장 폴더 자동 열기.</summary>
public bool OpenFolderOnComplete { get; set; } = false;
/// <summary>자막 우선 언어(ko/en/…, 빈 문자열=자막 안 받음).</summary>
public string SubtitleLanguage { get; set; } = "";
/// <summary>UC-D21 다운로드 예약 창("HH:mm-HH:mm", 빈 값=항상 허용).</summary>
public string? DownloadScheduleWindow { get; set; }
/// <summary>다운로드 속도 상한(kbps, 0=제한 없음).</summary>
public int MaxDownloadSpeedKbps { get; set; } = 0;
// ---- §F 설정창 ----
/// <summary>설정창 위치·크기 "Left,Top,Width,Height".</summary>
public string? SettingsWindowBounds { get; set; }
/// <summary>UI 언어: ko / en.</summary>
public string Language { get; set; } = "ko";
/// <summary>닫기 버튼으로 트레이로 최소화.</summary>
public bool MinimizeToTray { get; set; } = false;
/// <summary>Windows 시작 시 자동 실행.</summary>
public bool AutoStart { get; set; } = false;
/// <summary>재시도 횟수(UI 노출용 — Retries 와 동일 값을 설정창에서 편집).</summary>
public int RetriesUi { get => Retries; set => Retries = value; }
/// <summary>HTTP 프록시 서버(http://host:port, 빈 문자열=직접 연결).</summary>
public string ProxyServer { get; set; } = "";
// ---- §G 접근성 ----
/// <summary>저시력용 폰트 확대 배율(1.0~2.0). UiFontSize 와 곱해 적용.</summary>
public double UiFontScale { get; set; } = 1.0;
/// <summary>영상 자막 표시(플레이어에 자막 렌더 시도).</summary>
public bool ShowCaptions { get; set; } = true;
// ---- §H 인터랙션 ----
/// <summary>명령 키 → 조합 문자열(예: "newtab": "Ctrl+T"). 없으면 기본값.</summary>
public Dictionary<string, string> Shortcuts { get; set; } = new();
/// <summary>주소창에 붙여넣으면 즉시 이동.</summary>
public bool PasteAndGo { get; set; } = true;
/// <summary>주소창 포커스 시 전체 선택.</summary>
public bool FocusSelectsAddress { get; set; } = true;
/// <summary>새 탭 기본 줌 배율(0.1~5.0).</summary>
public double DefaultZoomFactor { get; set; } = 1.0;
// ---- §I 라이브러리·재생목록 ----
/// <summary>재생목록 반복 모드: none / one / all.</summary>
public string PlaylistLoopMode { get; set; } = "none";
// ---- §J 상태·알림 ----
/// <summary>토스트 표시 시간(ms).</summary>
public int ToastDurationMs { get; set; } = 4000;
/// <summary>절전 모드(전원 절약) 진입 시 다운로드 일시정지.</summary>
public bool PauseOnPowerSaver { get; set; } = true;
/// <summary>방해 금지(알림 음소거·토스트 억제).</summary>
public bool DoNotDisturb { get; set; } = false;
/// <summary>UC-S04 모든 설정을 새 인스턴스 기본값으로 되돌린다(원격 접속 토큰은 유지 — 기기 페어링 유지).</summary>
public void ResetToDefaults()
{
var fresh = new AppConfig();
foreach (var prop in typeof(AppConfig).GetProperties().Where(p => p.CanRead && p.CanWrite))
{
if (prop.Name == nameof(RemoteAccessToken)) continue;
try { prop.SetValue(this, prop.GetValue(fresh)); } catch { }
}
}
}