feat(settings): expose music quality preset
This commit is contained in:
@@ -158,6 +158,7 @@
|
||||
"bufferSizeWarning": "${heap}MB memory available. A ${size}MB buffer may affect playback.",
|
||||
"defaultQualityTitle": "Default Quality",
|
||||
"defaultQualityDescription": "Used when starting playback. Lower values reduce bandwidth.",
|
||||
"musicQualityTitle": "Music Quality",
|
||||
"subtitleStyling": "Subtitle Styling",
|
||||
"subtitleStylingDescription": "Customize subtitle appearance",
|
||||
"smallSkipDuration": "Small Skip Duration",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/// To regenerate, run: `dart run slang`
|
||||
///
|
||||
/// Locales: 16
|
||||
/// Strings: 22706 (1419 per locale)
|
||||
/// Strings: 22707 (1419 per locale)
|
||||
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint, unused_import
|
||||
|
||||
@@ -588,6 +588,9 @@ class TranslationsSettingsEn {
|
||||
/// en: 'Used when starting playback. Lower values reduce bandwidth.'
|
||||
String get defaultQualityDescription => 'Used when starting playback. Lower values reduce bandwidth.';
|
||||
|
||||
/// en: 'Music Quality'
|
||||
String get musicQualityTitle => 'Music Quality';
|
||||
|
||||
/// en: 'Subtitle Styling'
|
||||
String get subtitleStyling => 'Subtitle Styling';
|
||||
|
||||
@@ -5111,6 +5114,7 @@ extension on Translations {
|
||||
'settings.bufferSizeWarning' => ({required Object heap, required Object size}) => '${heap}MB memory available. A ${size}MB buffer may affect playback.',
|
||||
'settings.defaultQualityTitle' => 'Default Quality',
|
||||
'settings.defaultQualityDescription' => 'Used when starting playback. Lower values reduce bandwidth.',
|
||||
'settings.musicQualityTitle' => 'Music Quality',
|
||||
'settings.subtitleStyling' => 'Subtitle Styling',
|
||||
'settings.subtitleStylingDescription' => 'Customize subtitle appearance',
|
||||
'settings.smallSkipDuration' => 'Small Skip Duration',
|
||||
@@ -5474,9 +5478,9 @@ extension on Translations {
|
||||
'messages.removedFromContinueWatching' => 'Removed from Continue Watching',
|
||||
'messages.errorLoading' => ({required Object error}) => 'Error: ${error}',
|
||||
'messages.streamInterrupted' => 'The stream was interrupted. Press play or seek to retry.',
|
||||
'messages.fileInfoNotAvailable' => 'File information not available',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'messages.fileInfoNotAvailable' => 'File information not available',
|
||||
'messages.errorLoadingFileInfo' => ({required Object error}) => 'Error loading file info: ${error}',
|
||||
'messages.errorLoadingSeries' => 'Error loading series',
|
||||
'messages.musicNotSupported' => 'Music playback is not yet supported',
|
||||
@@ -5988,9 +5992,9 @@ extension on Translations {
|
||||
'downloads.manage' => 'Manage',
|
||||
'downloads.tvShows' => 'TV Shows',
|
||||
'downloads.movies' => 'Movies',
|
||||
'downloads.music' => 'Music',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'downloads.music' => 'Music',
|
||||
'downloads.tracksQueued' => ({required Object count}) => '${count} tracks queued for download',
|
||||
'downloads.noDownloads' => 'No downloads yet',
|
||||
'downloads.noDownloadsDescription' => 'Downloaded content will appear here for offline viewing',
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
|
||||
import '../../i18n/strings.g.dart';
|
||||
import '../../models/audio_quality_preset.dart';
|
||||
import '../../models/transcode_quality_preset.dart';
|
||||
import '../../mpv/player/platform/player_android.dart';
|
||||
import '../../utils/quality_preset_labels.dart';
|
||||
@@ -91,6 +92,7 @@ class _PlaybackSettingsScreenState extends State<PlaybackSettingsScreen> {
|
||||
if (exoActive) _dvConversionModeTile(),
|
||||
_bufferSizeTile(),
|
||||
_defaultQualityTile(),
|
||||
_musicQualityTile(),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -443,6 +445,19 @@ class _PlaybackSettingsScreenState extends State<PlaybackSettingsScreen> {
|
||||
encode: (p) => p,
|
||||
);
|
||||
|
||||
Widget _musicQualityTile() => SettingSelectionTile<AudioQualityPreset, AudioQualityPreset>(
|
||||
pref: SettingsService.musicQualityPreset,
|
||||
icon: Symbols.music_note_rounded,
|
||||
title: t.settings.musicQualityTitle,
|
||||
subtitleBuilder: _musicQualityLabel,
|
||||
options: AudioQualityPreset.values.map((p) => DialogOption(value: p, title: _musicQualityLabel(p))).toList(),
|
||||
decode: (p) => p,
|
||||
encode: (p) => p,
|
||||
);
|
||||
|
||||
String _musicQualityLabel(AudioQualityPreset preset) =>
|
||||
preset.isOriginal ? t.videoControls.qualityOriginal : '${preset.bitrateKbps} kbps';
|
||||
|
||||
Widget _mpvConfigTile() => SettingNavigationTile(
|
||||
icon: Symbols.tune_rounded,
|
||||
title: t.mpvConfig.title,
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:plezy/i18n/strings.g.dart';
|
||||
import 'package:plezy/models/audio_quality_preset.dart';
|
||||
import 'package:plezy/screens/settings/playback_settings_screen.dart';
|
||||
import 'package:plezy/services/settings_service.dart';
|
||||
import 'package:plezy/theme/mono_theme.dart';
|
||||
|
||||
import '../../test_helpers/prefs.dart';
|
||||
|
||||
void main() {
|
||||
setUp(() async {
|
||||
resetSharedPreferencesForTest(initialAsync: {'music_quality_preset': 'medium'});
|
||||
SettingsService.resetForTesting();
|
||||
await SettingsService.getInstance();
|
||||
LocaleSettings.setLocaleSync(AppLocale.en);
|
||||
});
|
||||
|
||||
testWidgets('shows and changes the persisted music quality', (tester) async {
|
||||
tester.view.devicePixelRatio = 1;
|
||||
tester.view.physicalSize = const Size(1000, 1400);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
|
||||
await tester.pumpWidget(MaterialApp(theme: monoTheme(dark: true), home: const PlaybackSettingsScreen()));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final title = find.text('Music Quality');
|
||||
await tester.scrollUntilVisible(title, 500, scrollable: find.byType(Scrollable).first);
|
||||
|
||||
final tile = find.widgetWithText(ListTile, 'Music Quality');
|
||||
expect(find.descendant(of: tile, matching: find.text('192 kbps')), findsOneWidget);
|
||||
|
||||
await tester.tap(title);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('128 kbps'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final settings = SettingsService.instance;
|
||||
expect(settings.read(SettingsService.musicQualityPreset), AudioQualityPreset.low);
|
||||
expect(settings.prefs.getString(SettingsService.musicQualityPreset.key), 'low');
|
||||
expect(find.descendant(of: tile, matching: find.text('128 kbps')), findsOneWidget);
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:plezy/models/audio_quality_preset.dart';
|
||||
import 'package:plezy/models/hotkey_model.dart';
|
||||
import 'package:plezy/services/base_shared_preferences_service.dart';
|
||||
import 'package:plezy/services/settings_service.dart';
|
||||
import 'package:plezy/services/trackers/tracker_constants.dart';
|
||||
import 'package:plezy/utils/platform_detector.dart';
|
||||
@@ -145,6 +147,23 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
group('SettingsService music quality', () {
|
||||
test('defaults to original and persists changes by enum name', () async {
|
||||
var settings = await SettingsService.getInstance();
|
||||
|
||||
expect(settings.read(SettingsService.musicQualityPreset), AudioQualityPreset.original);
|
||||
|
||||
await settings.write(SettingsService.musicQualityPreset, AudioQualityPreset.medium);
|
||||
expect(settings.prefs.getString(SettingsService.musicQualityPreset.key), 'medium');
|
||||
|
||||
BaseSharedPreferencesService.resetForTesting();
|
||||
SettingsService.resetForTesting();
|
||||
settings = await SettingsService.getInstance();
|
||||
|
||||
expect(settings.read(SettingsService.musicQualityPreset), AudioQualityPreset.medium);
|
||||
});
|
||||
});
|
||||
|
||||
group('SettingsService platform gates', () {
|
||||
test('audio passthrough stays available on desktop and Apple TV', () {
|
||||
expect(PlatformDetector.supportsAudioPassthrough(), isTrue);
|
||||
|
||||
Reference in New Issue
Block a user