mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-10-19 14:07:26 +02:00
fix(automix): use themed transition effect picker
This commit is contained in:
1 parent
e6c7213067
commit
ee8719cc5d
2 files changed
+133
-15
No files matched your search
@@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:spotiflac_android/l10n/l10n.dart';
|
||||
import 'package:spotiflac_android/models/automix_options.dart';
|
||||
import 'package:spotiflac_android/providers/settings_provider.dart';
|
||||
import 'package:spotiflac_android/widgets/app_bottom_sheet.dart';
|
||||
import 'package:spotiflac_android/widgets/settings_group.dart';
|
||||
|
||||
class AutoMixSettings extends ConsumerStatefulWidget {
|
||||
@@ -17,6 +18,53 @@ class _AutoMixSettingsState extends ConsumerState<AutoMixSettings> {
|
||||
double? _pitch;
|
||||
double? _speed;
|
||||
|
||||
void _showEffectPicker(
|
||||
BuildContext context,
|
||||
AutoMixEffect current,
|
||||
Map<AutoMixEffect, String> names,
|
||||
) {
|
||||
final notifier = ref.read(settingsProvider.notifier);
|
||||
showAppBottomSheet<void>(
|
||||
context: context,
|
||||
useRootNavigator: true,
|
||||
title: context.l10n.autoMixEffect,
|
||||
maxHeightFactor: 0.85,
|
||||
builder: (sheetContext) => SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
for (final effect in AutoMixEffect.values)
|
||||
Semantics(
|
||||
selected: effect == current,
|
||||
child: AppSheetOption(
|
||||
leading: Icon(switch (effect) {
|
||||
AutoMixEffect.auto => Icons.auto_awesome,
|
||||
AutoMixEffect.crossfade => Icons.compare_arrows,
|
||||
AutoMixEffect.muffled => Icons.graphic_eq,
|
||||
AutoMixEffect.echo => Icons.surround_sound,
|
||||
AutoMixEffect.pitch => Icons.music_note,
|
||||
AutoMixEffect.custom => Icons.tune,
|
||||
}),
|
||||
title: Text(names[effect]!),
|
||||
trailing: effect == current
|
||||
? Icon(
|
||||
Icons.check,
|
||||
color: Theme.of(sheetContext).colorScheme.primary,
|
||||
)
|
||||
: null,
|
||||
onTap: () {
|
||||
notifier.setAutoMixEffect(effect);
|
||||
Navigator.pop(sheetContext);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final settings = ref.watch(settingsProvider);
|
||||
@@ -83,21 +131,13 @@ class _AutoMixSettingsState extends ConsumerState<AutoMixSettings> {
|
||||
setState(() => _duration = null);
|
||||
},
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: DropdownButtonFormField<AutoMixEffect>(
|
||||
initialValue: settings.autoMixEffect,
|
||||
decoration: InputDecoration(labelText: l10n.autoMixEffect),
|
||||
items: [
|
||||
for (final effect in AutoMixEffect.values)
|
||||
DropdownMenuItem(value: effect, child: Text(names[effect]!)),
|
||||
],
|
||||
onChanged: enabled
|
||||
? (value) {
|
||||
if (value != null) notifier.setAutoMixEffect(value);
|
||||
}
|
||||
: null,
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.tune,
|
||||
title: l10n.autoMixEffect,
|
||||
subtitle: names[settings.autoMixEffect],
|
||||
onTap: enabled
|
||||
? () => _showEffectPicker(context, settings.autoMixEffect, names)
|
||||
: null,
|
||||
),
|
||||
if (settings.autoMixEffect == AutoMixEffect.pitch ||
|
||||
settings.autoMixEffect == AutoMixEffect.custom)
|
||||
|
||||
@@ -5,8 +5,12 @@ import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:spotiflac_android/l10n/l10n.dart';
|
||||
import 'package:spotiflac_android/models/automix_options.dart';
|
||||
import 'package:spotiflac_android/models/settings.dart';
|
||||
import 'package:spotiflac_android/models/theme_settings.dart';
|
||||
import 'package:spotiflac_android/providers/settings_provider.dart';
|
||||
import 'package:spotiflac_android/widgets/automix_settings.dart';
|
||||
import 'package:spotiflac_android/theme/app_theme.dart';
|
||||
import 'package:spotiflac_android/theme/mornye_theme.dart';
|
||||
import 'package:spotiflac_android/widgets/app_bottom_sheet.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets(
|
||||
@@ -50,7 +54,81 @@ void main() {
|
||||
for (final slider in tester.widgetList<Slider>(find.byType(Slider))) {
|
||||
expect(slider.onChanged, isNull);
|
||||
}
|
||||
await tester.tap(find.text('Transition effect'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(BottomSheet), findsNothing);
|
||||
expect(tester.takeException(), isNull);
|
||||
},
|
||||
);
|
||||
|
||||
for (final mornye in [false, true]) {
|
||||
testWidgets(
|
||||
'effect picker follows app theme and saves selection ($mornye)',
|
||||
(tester) async {
|
||||
SharedPreferences.setMockInitialValues({});
|
||||
tester.view.physicalSize = const Size(350, 600);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.reset);
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
initialSettingsProvider.overrideWithValue(
|
||||
const AppSettings(autoMix: true),
|
||||
),
|
||||
],
|
||||
);
|
||||
addTearDown(container.dispose);
|
||||
await tester.pumpWidget(
|
||||
UncontrolledProviderScope(
|
||||
container: container,
|
||||
child: MaterialApp(
|
||||
theme: mornye
|
||||
? MornyeTheme.build(
|
||||
Brightness.dark,
|
||||
accent: MornyeAccent.blue,
|
||||
)
|
||||
: AppTheme.light(seedColor: Colors.blue),
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
home: const MornyeSettingsTheme(
|
||||
child: Scaffold(
|
||||
body: SingleChildScrollView(child: AutoMixSettings()),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Transition effect'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(AppBottomSheet), findsOneWidget);
|
||||
expect(find.byType(AppSheetOption), findsNWidgets(6));
|
||||
final context = tester.element(find.byType(AppBottomSheet));
|
||||
expect(context.isMornye, mornye);
|
||||
final selected = tester
|
||||
.widgetList<AppSheetOption>(find.byType(AppSheetOption))
|
||||
.singleWhere((option) => option.trailing != null);
|
||||
expect((selected.title as Text).data, 'Auto');
|
||||
expect(
|
||||
(selected.trailing as Icon).color,
|
||||
Theme.of(context).colorScheme.primary,
|
||||
);
|
||||
final custom = find.descendant(
|
||||
of: find.byType(AppBottomSheet),
|
||||
matching: find.text('Custom'),
|
||||
);
|
||||
await tester.ensureVisible(custom);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(custom);
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
container.read(settingsProvider).autoMixEffect,
|
||||
AutoMixEffect.custom,
|
||||
);
|
||||
expect(find.byType(BottomSheet), findsNothing);
|
||||
expect(find.text('Custom'), findsOneWidget);
|
||||
expect(find.byType(Slider), findsNWidgets(2));
|
||||
expect(tester.takeException(), isNull);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user