From e82822769385db2984bbc996c7d6a4e6e8f57bf4 Mon Sep 17 00:00:00 2001 From: RyuJongJin <266630912+RyuJongJin@users.noreply.github.com> Date: Fri, 23 Oct 2026 00:12:48 +0900 Subject: [PATCH] =?UTF-8?q?=EC=84=A4=EC=A0=95=20A:=20=EC=9E=AC=EC=83=9D=20?= =?UTF-8?q?=EB=B6=84=EC=95=BC=20(PlaybackSettings)=20-=20=EB=8F=99?= =?UTF-8?q?=EC=98=81=EC=83=81=20=EC=97=B4=EA=B8=B0=20=C2=B7=20=EC=9E=AC?= =?UTF-8?q?=EC=83=9D=20=EB=AA=A9=EB=A1=9D=20=C2=B7=20=EC=99=B8=EB=B6=80=20?= =?UTF-8?q?=ED=94=8C=EB=A0=88=EC=9D=B4=EC=96=B4=20=C2=B7=20=EC=9E=90?= =?UTF-8?q?=EB=A7=89=20=ED=81=AC=EA=B8=B0=20=C2=B7=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EC=9E=90=EB=A7=89=20=EC=96=B8=EC=96=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- lib/app/app_controller.dart | 8 ++--- lib/app/settings.dart | 36 ++++---------------- lib/app/settings/playback_settings.dart | 44 +++++++++++++++++++++++++ lib/main.dart | 8 ++--- lib/ui/player_page.dart | 4 +-- lib/ui/settings/media_sections.dart | 22 ++++++------- test/ftp_test.dart | 2 +- test/i18n_small_test.dart | 6 ++-- test/player_test.dart | 8 ++--- test/sftp_stream_test.dart | 2 +- test/small_items_test.dart | 10 +++--- test/smb_test.dart | 2 +- test/webdav_test.dart | 2 +- 13 files changed, 88 insertions(+), 66 deletions(-) create mode 100644 lib/app/settings/playback_settings.dart diff --git a/lib/app/app_controller.dart b/lib/app/app_controller.dart index 6c5ca4e..fa8f0b5 100644 --- a/lib/app/app_controller.dart +++ b/lib/app/app_controller.dart @@ -153,9 +153,9 @@ class AppController extends ChangeNotifier { } void _applySettings() { - playerSubtitleScale.value = settings.subtitleScale; + playerSubtitleScale.value = settings.playback.subtitleScale; // 61: 기본 자막 언어 (MKV 기본 자막 트랙 · 플레이어가 먼저 켜는 자막) - preferredSubtitleSetting = settings.preferredSubtitleLanguage; + preferredSubtitleSetting = settings.playback.preferredSubtitleLanguage; // WebDAV 서버 (파일 탐색기 · Rsync 화면 · 복사 · 동기화가 dav:// 경로로 쓴다) DavRegistry.configure(settings.remote.webdavServers); // 88: SFTP 서버 (sftp:// 경로) @@ -1294,7 +1294,7 @@ class AppController extends ChangeNotifier { final videos = files.where((f) => isVideoFile(f) || isAudioFile(f)).toList(); if (videos.isEmpty) return null; final ext = p.extension(videos.first).replaceFirst('.', '').toLowerCase(); - final program = settings.externalPlayers[ext]; + final program = settings.playback.externalPlayers[ext]; if (!internal && program != null && program.isNotEmpty) { // WebDAV 는 스트리밍 주소로 넘긴다 (아이디 · 비밀번호는 넣지 않음 - 55) if (external != null) { @@ -1312,7 +1312,7 @@ class AppController extends ChangeNotifier { final siblings = isDav(videos.first) ? [for (final e in await vList(vDirname(videos.first))) if (!e.isDir) e.path] : await services.storage.listFiles(p.dirname(videos.first)); - return buildPlaylist(videos.first, siblings, settings.playlistMode); + return buildPlaylist(videos.first, siblings, settings.playback.playlistMode); } /// 재생 중 고를 수 있는 외부 자막: 같은 폴더의 자막 + jj_mkv 안의 파일명_*.srt diff --git a/lib/app/settings.dart b/lib/app/settings.dart index 4e48623..846af0b 100644 --- a/lib/app/settings.dart +++ b/lib/app/settings.dart @@ -4,9 +4,9 @@ import 'package:path/path.dart' as p; import '../core/reader_sources.dart' show defaultImageExtensions; import '../core/download_detect.dart'; -import '../core/playlist.dart'; import 'settings/records.dart'; import 'settings/settings_group.dart'; +import 'settings/playback_settings.dart'; import 'settings/mkv_settings.dart'; import 'settings/display_settings.dart'; import 'settings/remote_settings.dart'; @@ -25,6 +25,7 @@ import 'settings/explorer_settings.dart'; export 'settings/records.dart'; export 'settings/settings_group.dart'; export 'settings/settings_store.dart'; +export 'settings/playback_settings.dart'; export 'settings/mkv_settings.dart'; export 'settings/display_settings.dart'; export 'settings/remote_settings.dart'; @@ -71,15 +72,11 @@ class AppSettings { - /// 탐색기에서 동영상을 열었을 때 (더블클릭 · 연결 프로그램): 'play' 바로 재생 / 'add' 편집 목록에 추가 - String openFileAction = 'play'; - /// 프로그램이 켜져 있을 때 탐색기에서 연 동영상 재생: 'same' 켜져 있는 창에서 / 'new' 새 재생 창 - String openFileWindow = 'same'; @@ -181,15 +178,11 @@ class AppSettings { bool recycleOnDelete = true; - /// 61: 기본 자막 언어 (MKV 의 기본 자막 트랙 · 플레이어가 먼저 켜는 자막). '' = 화면 언어 따르기, 그 밖은 자막 언어 코드 (ko · ja …) - String preferredSubtitleLanguage = ''; /// 39: 켤 때 "모든 파일 접근" 안내를 한 번 보였는지 (그 뒤로는 파일 탐색기 안의 안내로) bool allFilesHintShown = false; - /// 내장 플레이어 자막 글자 크기 배율 (0.5 ~ 2.5, 기본 1) - double subtitleScale = 1.0; @@ -232,11 +225,7 @@ class AppSettings { - /// 동영상 하나를 재생할 때 재생 목록 (기본: 같은 시리즈) - PlaylistMode playlistMode = PlaylistMode.series; - /// 확장자별 재생 프로그램 (없으면 내장 플레이어): 'system' 또는 실행 파일 경로 - Map externalPlayers = {}; @@ -284,8 +273,11 @@ class AppSettings { /// MKV · 자막 만들기 (저장 위치 · 이동 버튼 · 인코딩 · AI 자막 · OpenSubtitles) final mkv = MkvSettings(); + /// 재생 (동영상 열기 · 재생 목록 · 외부 플레이어 · 자막 크기 · 기본 자막 언어) + final playback = PlaybackSettings(); + /// 설정 분야들 (설정 A) - 저마다 자기 키를 읽고 쓴다. toJson · fromJson 은 이 목록을 돌며 합치기만 한다 - List get groups => [explorer, network, tor, copy, aiImage, reader, download, browser, run, vault, tools, remote, display, mkv]; + List get groups => [explorer, network, tor, copy, aiImage, reader, download, browser, run, vault, tools, remote, display, mkv, playback]; /// [plainSecrets]: 안전 저장소를 쓸 수 없을 때만 (예전 파일에 있던 비밀 값을 잃지 않게) 예전처럼 파일에 둔다 Map toJson({bool plainSecrets = false}) { @@ -294,8 +286,6 @@ class AppSettings { ...stripSecrets(extra), 'folderBookmarks': [for (final b in folderBookmarks) b.toJson()], 'cookieScopeV2': true, - 'openFileAction': openFileAction, - 'openFileWindow': openFileWindow, 'robocopyLinksV1': true, 'imageExts': imageExts, 'cleanupPrechecked': cleanupPrechecked, @@ -303,12 +293,8 @@ class AppSettings { 'allowInnerToOuter': allowInnerToOuter, 'rememberPasswords': rememberPasswords, 'recycleOnDelete': recycleOnDelete, - 'preferredSubtitleLanguage': preferredSubtitleLanguage, // 116: 예전 판의 표시 ('allFilesHintShown') 는 권한이 없어진 것을 몰라 다시 띄우지 못했다 → 새 이름으로 한 번 더 'allFilesHint2': allFilesHintShown, - 'subtitleScale': subtitleScale, - 'playlistMode': playlistMode.name, - 'externalPlayers': externalPlayers, }; for (final g in groups) { g.write(j, plainSecrets: plainSecrets); @@ -317,12 +303,8 @@ class AppSettings { } factory AppSettings.fromJson(Map j) { - T pick(List values, Object? name, T fallback) => - values.firstWhere((v) => v.name == name, orElse: () => fallback); final s = AppSettings() ..folderBookmarks = [for (final x in (j['folderBookmarks'] as List?) ?? const []) ?FolderBookmark.fromJson(x)] - ..openFileAction = j['openFileAction'] == 'add' ? 'add' : 'play' - ..openFileWindow = j['openFileWindow'] == 'new' ? 'new' : 'same' ..imageExts = j['imageExts'] is List ? [for (final x in j['imageExts'] as List) '$x'.toLowerCase()] : [...defaultImageExtensions] @@ -333,11 +315,7 @@ class AppSettings { ..allowInnerToOuter = j['allowInnerToOuter'] != false ..rememberPasswords = j['rememberPasswords'] != false ..recycleOnDelete = j['recycleOnDelete'] != false - ..preferredSubtitleLanguage = j['preferredSubtitleLanguage'] is String ? j['preferredSubtitleLanguage'] as String : '' - ..allFilesHintShown = j['allFilesHint2'] == true - ..subtitleScale = ((j['subtitleScale'] as num?)?.toDouble() ?? 1.0).clamp(0.5, 2.5) - ..playlistMode = pick(PlaylistMode.values, j['playlistMode'], PlaylistMode.series) - ..externalPlayers = ((j['externalPlayers'] as Map?) ?? const {}).cast(); + ..allFilesHintShown = j['allFilesHint2'] == true; // 분야를 먼저 읽는다 - 바뀐 기본값 알림 ([_migrated]) 이 분야의 값을 본다 for (final g in s.groups) { g.read(j); diff --git a/lib/app/settings/playback_settings.dart b/lib/app/settings/playback_settings.dart new file mode 100644 index 0000000..417a7bd --- /dev/null +++ b/lib/app/settings/playback_settings.dart @@ -0,0 +1,44 @@ +import '../../core/playlist.dart'; +import 'settings_group.dart'; + +/// 약속 (설정 A): 환경 설정 > 재생 (동영상 열기 · 재생 목록 · 외부 플레이어 · 자막 크기 · 기본 자막 언어) - 자기 키 (이름 · 처음 값 · 읽기 · 쓰기) 를 스스로 갖는다. +/// 설정 하나를 더할 때는 이 파일만 고친다. 저장 파일의 키 이름은 예전 그대로 (평평한 키) +class PlaybackSettings implements SettingsGroup { + /// 탐색기에서 동영상을 열었을 때 (더블클릭 · 연결 프로그램): 'play' 바로 재생 / 'add' 편집 목록에 추가 + String openFileAction = 'play'; + + /// 프로그램이 켜져 있을 때 탐색기에서 연 동영상 재생: 'same' 켜져 있는 창에서 / 'new' 새 재생 창 + String openFileWindow = 'same'; + + /// 61: 기본 자막 언어 (MKV 의 기본 자막 트랙 · 플레이어가 먼저 켜는 자막). '' = 화면 언어 따르기, 그 밖은 자막 언어 코드 (ko · ja …) + String preferredSubtitleLanguage = ''; + + /// 내장 플레이어 자막 글자 크기 배율 (0.5 ~ 2.5, 기본 1) + double subtitleScale = 1.0; + + /// 동영상 하나를 재생할 때 재생 목록 (기본: 같은 시리즈) + PlaylistMode playlistMode = PlaylistMode.series; + + /// 확장자별 재생 프로그램 (없으면 내장 플레이어): 'system' 또는 실행 파일 경로 + Map externalPlayers = {}; + + @override + void write(Map j, {required bool plainSecrets}) { + j['openFileAction'] = openFileAction; + j['openFileWindow'] = openFileWindow; + j['playlistMode'] = playlistMode.name; + j['externalPlayers'] = externalPlayers; + j['subtitleScale'] = subtitleScale; + j['preferredSubtitleLanguage'] = preferredSubtitleLanguage; + } + + @override + void read(Map j) { + openFileAction = j['openFileAction'] == 'add' ? 'add' : 'play'; + openFileWindow = j['openFileWindow'] == 'new' ? 'new' : 'same'; + preferredSubtitleLanguage = j['preferredSubtitleLanguage'] is String ? j['preferredSubtitleLanguage'] as String : ''; + subtitleScale = ((j['subtitleScale'] as num?)?.toDouble() ?? 1.0).clamp(0.5, 2.5); + playlistMode = pickEnum(PlaylistMode.values, j['playlistMode'], PlaylistMode.series); + externalPlayers = ((j['externalPlayers'] as Map?) ?? const {}).cast(); + } +} diff --git a/lib/main.dart b/lib/main.dart index 4f06855..e3aa90b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -367,7 +367,7 @@ Future main(List args) async { if (videos.isEmpty) return; // 어느 쪽이든 MKV 화면의 목록에는 들어간다 final added = controller.addVideos(videos, allowOutputFolder: true); - if (controller.settings.openFileAction == 'add') { + if (controller.settings.playback.openFileAction == 'add') { await added; final first = controller.videos.where((v) => videos.any((f) => p.equals(f, v.path))).firstOrNull; if (first != null) controller.select(first); @@ -444,7 +444,7 @@ Future openFromOtherApp( if (ctx == null || !ctx.mounted) return; if (paths.isNotEmpty) { final added = c.addVideos(paths, allowOutputFolder: true); - if (c.settings.openFileAction == 'add') { + if (c.settings.playback.openFileAction == 'add') { await added; final first = c.videos.where((v) => paths.any((f) => p.equals(f, v.path))).firstOrNull; if (first != null) c.select(first); @@ -535,9 +535,9 @@ void watchDnsFailure(GlobalKey messengerKey, AppControll /// 탐색기에서 연 동영상을 새 재생 창으로 띄울지 (재생 요청 + 설정 "새 창에서") bool wantsNewPlayerWindow(LaunchRequest r, AppSettings s) => - s.openFileWindow == 'new' && + s.playback.openFileWindow == 'new' && r.files.any(isVideoFile) && - (r.action == LaunchAction.play || (r.action == LaunchAction.add && s.openFileAction == 'play')); + (r.action == LaunchAction.play || (r.action == LaunchAction.add && s.playback.openFileAction == 'play')); extension on String { String ifEmptyText(String other) => isEmpty ? other : this; diff --git a/lib/ui/player_page.dart b/lib/ui/player_page.dart index 050b36d..1c4343a 100644 --- a/lib/ui/player_page.dart +++ b/lib/ui/player_page.dart @@ -405,8 +405,8 @@ class _PlayerPageState extends State { // 자막 글자 크기 (설정에 남는다) SubmenuButton(menuChildren: [ for (final r in const [0.6, 0.8, 1.0, 1.2, 1.5, 2.0, 2.5]) - item('${(r * 100).round()}%', () => c.updateSettings((x) => x.subtitleScale = r), - checked: (c.settings.subtitleScale - r).abs() < 0.01), + item('${(r * 100).round()}%', () => c.updateSettings((x) => x.playback.subtitleScale = r), + checked: (c.settings.playback.subtitleScale - r).abs() < 0.01), ], child: Text(tr('자막 크기'))), if (s.audioTracks.length > 1) SubmenuButton(menuChildren: [ diff --git a/lib/ui/settings/media_sections.dart b/lib/ui/settings/media_sections.dart index 7da6bd7..d297a40 100644 --- a/lib/ui/settings/media_sections.dart +++ b/lib/ui/settings/media_sections.dart @@ -42,8 +42,8 @@ class _MkvSettingsSectionState extends State { title: Text(tr('기본 자막 언어')), subtitle: Text(tr('MKV 의 기본 자막 트랙 · 플레이어가 먼저 켜는 자막')), trailing: SubtitleLanguagePicker( - value: s.preferredSubtitleLanguage, - onChanged: (v) => c.updateSettings((x) => x.preferredSubtitleLanguage = v), + value: s.playback.preferredSubtitleLanguage, + onChanged: (v) => c.updateSettings((x) => x.playback.preferredSubtitleLanguage = v), ), ), SettingTile( @@ -219,11 +219,11 @@ class _PlaySettingsSectionState extends State { title: Text(tr('동영상 하나를 재생할 때')), subtitle: Text(tr('시리즈: file_001 · file_002, S01E01 · S01E02 처럼 번호만 다른 파일')), trailing: DropdownButton( - value: s.playlistMode, + value: s.playback.playlistMode, items: [ for (final m in PlaylistMode.values) DropdownMenuItem(value: m, child: Text(m.label)), ], - onChanged: (m) => c.updateSettings((x) => x.playlistMode = m!), + onChanged: (m) => c.updateSettings((x) => x.playback.playlistMode = m!), ), ), SettingTile( @@ -232,12 +232,12 @@ class _PlaySettingsSectionState extends State { ? tr('더블클릭 · 연결 프로그램으로 JJ_MKVMaker 를 골랐을 때 (오른쪽 클릭 메뉴는 그대로)') : tr('파일 앱의 "다음으로 열기" · 공유에서 JJ_MKVMaker 를 골랐을 때')), trailing: DropdownButton( - value: s.openFileAction, + value: s.playback.openFileAction, items: [ DropdownMenuItem(value: 'play', child: Text(tr('바로 재생 (기본)'))), DropdownMenuItem(value: 'add', child: Text(tr('편집 목록에 추가 (MKV 만들기 대상)'))), ], - onChanged: (v) => c.updateSettings((x) => x.openFileAction = v!), + onChanged: (v) => c.updateSettings((x) => x.playback.openFileAction = v!), ), ), if (desk) ...[ @@ -245,12 +245,12 @@ class _PlaySettingsSectionState extends State { title: Text(tr('탐색기에서 연 동영상을 재생할 창')), subtitle: Text(tr('프로그램이 이미 켜져 있을 때. 새 창은 재생만 하는 창이며 닫으면 그 창만 끝납니다')), trailing: DropdownButton( - value: s.openFileWindow, + value: s.playback.openFileWindow, items: [ DropdownMenuItem(value: 'same', child: Text(tr('켜져 있는 창에서 (기본)'))), DropdownMenuItem(value: 'new', child: Text(tr('새 창에서'))), ], - onChanged: (v) => c.updateSettings((x) => x.openFileWindow = v!), + onChanged: (v) => c.updateSettings((x) => x.playback.openFileWindow = v!), ), ), ExternalPlayersTile(c: c), @@ -316,13 +316,13 @@ class ExternalPlayersTile extends StatelessWidget { @override Widget build(BuildContext context) { - final map = c.settings.externalPlayers; + final map = c.settings.playback.externalPlayers; final vlc = c.services.shell.vlcPath; Future set(String ext, String? v) => c.updateSettings((x) { if (v == null || v.isEmpty) { - x.externalPlayers.remove(ext); + x.playback.externalPlayers.remove(ext); } else { - x.externalPlayers[ext] = v; + x.playback.externalPlayers[ext] = v; } }); diff --git a/test/ftp_test.dart b/test/ftp_test.dart index eda95a6..23c6961 100644 --- a/test/ftp_test.dart +++ b/test/ftp_test.dart @@ -373,7 +373,7 @@ void main() { File(p.join(root.path, '영상', '메모.txt')).writeAsStringSync('t'); addTearDown(RemoteStreamBridge.close); final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); - c.settings.playlistMode = PlaylistMode.folder; + c.settings.playback.playlistMode = PlaylistMode.folder; final plan = await c.preparePlayback(['ftp://f1/영상/1화.mkv']); expect(plan!.$1, ['ftp://f1/영상/1화.mkv', 'ftp://f1/영상/2화.mkv'], reason: '같은 폴더의 동영상만 차례로 (다음 화)'); diff --git a/test/i18n_small_test.dart b/test/i18n_small_test.dart index f962579..2259234 100644 --- a/test/i18n_small_test.dart +++ b/test/i18n_small_test.dart @@ -55,7 +55,7 @@ void main() { test('기본 자막 언어 설정: 화면 언어 따르기 (처음 값) · 고른 언어가 화면 언어보다 먼저 · 저장', () async { addTearDown(() => preferredSubtitleSetting = ''); - expect(AppSettings().preferredSubtitleLanguage, '', reason: '처음 값은 화면 언어 따르기'); + expect(AppSettings().playback.preferredSubtitleLanguage, '', reason: '처음 값은 화면 언어 따르기'); await i18n.apply('ja', save: false); preferredSubtitleSetting = 'ko'; // 화면은 일본어, 자막은 한국어 expect(preferredDefaultLanguage, 'kor'); @@ -65,8 +65,8 @@ void main() { expect(preferredDefaultLanguage, 'vie'); preferredSubtitleSetting = ''; expect(preferredDefaultLanguage, 'jpn'); - final s = AppSettings()..preferredSubtitleLanguage = 'zh-Hans'; - expect(AppSettings.fromJson(s.toJson()).preferredSubtitleLanguage, 'zh-Hans'); + final s = AppSettings()..playback.preferredSubtitleLanguage = 'zh-Hans'; + expect(AppSettings.fromJson(s.toJson()).playback.preferredSubtitleLanguage, 'zh-Hans'); }); test('Android 저장소 이름: 내장 · SD 카드는 앱 화면 언어로, USB 등은 기기 이름 그대로', () async { diff --git a/test/player_test.dart b/test/player_test.dart index c58a40a..9c530ea 100644 --- a/test/player_test.dart +++ b/test/player_test.dart @@ -147,18 +147,18 @@ void main() { final play = LaunchRequest.parse(['--play', r'D:.mkv']); final sub = LaunchRequest.parse(['--subtitle', r'D:.mkv']); final s = AppSettings(); - expect([s.openFileAction, s.openFileWindow], ['play', 'same']); + expect([s.playback.openFileAction, s.playback.openFileWindow], ['play', 'same']); expect(wantsNewPlayerWindow(open, s), isFalse); // 기본: 켜져 있는 창에서 - s.openFileWindow = 'new'; + s.playback.openFileWindow = 'new'; expect(wantsNewPlayerWindow(open, s), isTrue); expect(wantsNewPlayerWindow(play, s), isTrue); expect(wantsNewPlayerWindow(sub, s), isFalse); // 자막 만들기는 원래 창 expect(wantsNewPlayerWindow(LaunchRequest.parse(const []), s), isFalse); - s.openFileAction = 'add'; + s.playback.openFileAction = 'add'; expect(wantsNewPlayerWindow(open, s), isFalse); // 목록에 추가는 원래 창 expect(wantsNewPlayerWindow(play, s), isTrue); final back = AppSettings.fromJson(s.toJson()); - expect([back.openFileAction, back.openFileWindow], ['add', 'new']); + expect([back.playback.openFileAction, back.playback.openFileWindow], ['add', 'new']); }); test('Android 화면 방향: 기본 자동, 가로 · 세로 고정 저장, 예전 기본 (가로 고정) 은 한 번 자동으로', () { diff --git a/test/sftp_stream_test.dart b/test/sftp_stream_test.dart index b1b29fa..f8feb20 100644 --- a/test/sftp_stream_test.dart +++ b/test/sftp_stream_test.dart @@ -85,7 +85,7 @@ void main() { test('같은 폴더 동영상 목록 · 다리로 스트리밍 (Range · 건너뛰기) · 다음 파일 · 그 자막', () async { final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); - c.settings.playlistMode = PlaylistMode.folder; + c.settings.playback.playlistMode = PlaylistMode.folder; final plan = await c.preparePlayback(['sftp://s1/영상/1화.mkv']); expect(plan!.$1, ['sftp://s1/영상/1화.mkv', 'sftp://s1/영상/2화.mkv'], reason: '같은 폴더의 동영상만 차례로'); diff --git a/test/small_items_test.dart b/test/small_items_test.dart index 9100a01..cac5b7e 100644 --- a/test/small_items_test.dart +++ b/test/small_items_test.dart @@ -16,12 +16,12 @@ void main() { setUp(() => c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService()))); test('자막 글자 크기: 설정에 남고 플레이어에 바로 반영', () async { - await c.updateSettings((s) => s.subtitleScale = 1.5); + await c.updateSettings((s) => s.playback.subtitleScale = 1.5); expect(playerSubtitleScale.value, 1.5); - expect(AppSettings.fromJson(c.settings.toJson()).subtitleScale, 1.5); - expect(AppSettings.fromJson({'subtitleScale': 9}).subtitleScale, 2.5); - expect(AppSettings.fromJson({}).subtitleScale, 1.0); - await c.updateSettings((s) => s.subtitleScale = 1.0); + expect(AppSettings.fromJson(c.settings.toJson()).playback.subtitleScale, 1.5); + expect(AppSettings.fromJson({'subtitleScale': 9}).playback.subtitleScale, 2.5); + expect(AppSettings.fromJson({}).playback.subtitleScale, 1.0); + await c.updateSettings((s) => s.playback.subtitleScale = 1.0); }); test('WebDAV 가 끼면 탐색기 복사 확인 창에 robocopy 가 아니라 실제 방법 (현재 방식)', () { diff --git a/test/smb_test.dart b/test/smb_test.dart index 1314938..ef73593 100644 --- a/test/smb_test.dart +++ b/test/smb_test.dart @@ -323,7 +323,7 @@ void main() { }); addTearDown(RemoteStreamBridge.close); final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); - c.settings.playlistMode = PlaylistMode.folder; + c.settings.playback.playlistMode = PlaylistMode.folder; final plan = await c.preparePlayback(['smb://m1/영상/1화.mkv']); expect(plan!.$1, ['smb://m1/영상/1화.mkv', 'smb://m1/영상/2화.mkv'], reason: '같은 폴더의 동영상만 차례로 (다음 화)'); diff --git a/test/webdav_test.dart b/test/webdav_test.dart index fa472f2..6aec386 100644 --- a/test/webdav_test.dart +++ b/test/webdav_test.dart @@ -186,7 +186,7 @@ void main() { expect(await res.transform(const SystemEncoding().decoder).join(), 'v1'); http.close(); final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); - c.settings.playlistMode = PlaylistMode.folder; + c.settings.playback.playlistMode = PlaylistMode.folder; final before = server.requests.where((r) => r.startsWith('GET')).length; final plan = await c.preparePlayback(['dav://$id/영상/1화.mkv']); expect(plan!.$1, ['dav://$id/영상/1화.mkv', 'dav://$id/영상/2화.mkv']);