mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-07 21:48:14 -08:00
feat: Bunch of small UI improvements for native player
This commit is contained in:
parent
66ffc8c112
commit
edbd8d467c
23 changed files with 329 additions and 327 deletions
|
|
@ -98,7 +98,7 @@ void main(List<String> args) async {
|
|||
applicationInfoProvider.overrideWith((ref) => applicationInfo),
|
||||
crashLogProvider.overrideWith((ref) => crashProvider),
|
||||
argumentsStateProvider.overrideWith((ref) => ArgumentsModel.fromArguments(args, leanBackEnabled)),
|
||||
syncProvider.overrideWith((ref) => SyncNotifier(ref, applicationDirectory))
|
||||
syncProvider.overrideWith((ref) => SyncNotifier(ref, applicationDirectory)),
|
||||
],
|
||||
child: AdaptiveLayoutBuilder(
|
||||
child: (context) => const Main(),
|
||||
|
|
|
|||
57
lib/providers/settings/pigeon_player_settings_provider.dart
Normal file
57
lib/providers/settings/pigeon_player_settings_provider.dart
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'package:fladder/models/items/media_segments_model.dart';
|
||||
import 'package:fladder/providers/settings/client_settings_provider.dart';
|
||||
import 'package:fladder/providers/settings/video_player_settings_provider.dart';
|
||||
import 'package:fladder/providers/user_provider.dart';
|
||||
import 'package:fladder/src/player_settings_helper.g.dart' as pigeon;
|
||||
|
||||
final pigeonPlayerSettingsSyncProvider = Provider<void>((ref) {
|
||||
void sendSettings() {
|
||||
final userData = ref.read(userProvider);
|
||||
final color = ref.read(
|
||||
clientSettingsProvider.select(
|
||||
(value) => value.themeColor?.color.toARGB32(),
|
||||
),
|
||||
);
|
||||
final value = ref.read(videoPlayerSettingsProvider);
|
||||
|
||||
if (!kIsWeb && Platform.isAndroid) {
|
||||
pigeon.PlayerSettingsPigeon().sendPlayerSettings(
|
||||
pigeon.PlayerSettings(
|
||||
enableTunneling: value.enableTunneling,
|
||||
skipTypes: value.segmentSkipSettings.map(
|
||||
(key, value) => MapEntry(
|
||||
switch (key) {
|
||||
MediaSegmentType.unknown => pigeon.SegmentType.intro,
|
||||
MediaSegmentType.commercial => pigeon.SegmentType.commercial,
|
||||
MediaSegmentType.preview => pigeon.SegmentType.preview,
|
||||
MediaSegmentType.recap => pigeon.SegmentType.recap,
|
||||
MediaSegmentType.outro => pigeon.SegmentType.outro,
|
||||
MediaSegmentType.intro => pigeon.SegmentType.intro,
|
||||
},
|
||||
switch (value) {
|
||||
SegmentSkip.none => pigeon.SegmentSkip.none,
|
||||
SegmentSkip.askToSkip => pigeon.SegmentSkip.ask,
|
||||
SegmentSkip.skip => pigeon.SegmentSkip.skip,
|
||||
},
|
||||
),
|
||||
),
|
||||
themeColor: color,
|
||||
skipBackward: (userData?.userSettings?.skipBackDuration ?? const Duration(seconds: 15)).inMilliseconds,
|
||||
skipForward: (userData?.userSettings?.skipForwardDuration ?? const Duration(seconds: 30)).inMilliseconds,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ref.listen(userProvider, (_, __) => sendSettings());
|
||||
ref.listen(clientSettingsProvider, (_, __) => sendSettings());
|
||||
ref.listen(videoPlayerSettingsProvider, (_, __) => sendSettings());
|
||||
|
||||
sendSettings();
|
||||
});
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
|
|
@ -8,13 +5,10 @@ import 'package:collection/collection.dart';
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:screen_brightness/screen_brightness.dart';
|
||||
|
||||
import 'package:fladder/models/items/media_segments_model.dart';
|
||||
import 'package:fladder/models/settings/key_combinations.dart';
|
||||
import 'package:fladder/models/settings/video_player_settings.dart';
|
||||
import 'package:fladder/providers/shared_provider.dart';
|
||||
import 'package:fladder/providers/user_provider.dart';
|
||||
import 'package:fladder/providers/video_player_provider.dart';
|
||||
import 'package:fladder/src/player_settings_helper.g.dart' as pigeon;
|
||||
|
||||
final videoPlayerSettingsProvider =
|
||||
StateNotifierProvider<VideoPlayerSettingsProviderNotifier, VideoPlayerSettingsModel>((ref) {
|
||||
|
|
@ -33,34 +27,6 @@ class VideoPlayerSettingsProviderNotifier extends StateNotifier<VideoPlayerSetti
|
|||
final oldState = super.state;
|
||||
super.state = value;
|
||||
ref.read(sharedUtilityProvider).videoPlayerSettings = value;
|
||||
if (!kIsWeb && Platform.isAndroid) {
|
||||
final userData = ref.read(userProvider);
|
||||
pigeon.PlayerSettingsPigeon().sendPlayerSettings(
|
||||
pigeon.PlayerSettings(
|
||||
enableTunneling: value.enableTunneling,
|
||||
skipTypes: value.segmentSkipSettings.map(
|
||||
(key, value) => MapEntry(
|
||||
switch (key) {
|
||||
MediaSegmentType.unknown => pigeon.SegmentType.intro,
|
||||
MediaSegmentType.commercial => pigeon.SegmentType.commercial,
|
||||
MediaSegmentType.preview => pigeon.SegmentType.preview,
|
||||
MediaSegmentType.recap => pigeon.SegmentType.recap,
|
||||
MediaSegmentType.outro => pigeon.SegmentType.outro,
|
||||
MediaSegmentType.intro => pigeon.SegmentType.intro,
|
||||
},
|
||||
switch (value) {
|
||||
SegmentSkip.none => pigeon.SegmentSkip.none,
|
||||
SegmentSkip.askToSkip => pigeon.SegmentSkip.ask,
|
||||
SegmentSkip.skip => pigeon.SegmentSkip.skip,
|
||||
},
|
||||
),
|
||||
),
|
||||
skipBackward: (userData?.userSettings?.skipBackDuration ?? const Duration(seconds: 15)).inMilliseconds,
|
||||
skipForward: (userData?.userSettings?.skipForwardDuration ?? const Duration(seconds: 30)).inMilliseconds,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (!oldState.playerSame(value)) {
|
||||
ref.read(videoPlayerProvider.notifier).init();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import 'package:fladder/providers/settings/book_viewer_settings_provider.dart';
|
|||
import 'package:fladder/providers/settings/client_settings_provider.dart';
|
||||
import 'package:fladder/providers/settings/home_settings_provider.dart';
|
||||
import 'package:fladder/providers/settings/photo_view_settings_provider.dart';
|
||||
import 'package:fladder/providers/settings/pigeon_player_settings_provider.dart';
|
||||
import 'package:fladder/providers/settings/subtitle_settings_provider.dart';
|
||||
import 'package:fladder/providers/settings/video_player_settings_provider.dart';
|
||||
import 'package:fladder/providers/user_provider.dart';
|
||||
|
|
@ -25,6 +26,9 @@ final sharedPreferencesProvider = Provider<SharedPreferences>((ref) {
|
|||
|
||||
final sharedUtilityProvider = Provider<SharedUtility>((ref) {
|
||||
final sharedPrefs = ref.watch(sharedPreferencesProvider);
|
||||
|
||||
//Init pigeon settings sync for native
|
||||
ref.read(pigeonPlayerSettingsSyncProvider);
|
||||
return SharedUtility(ref: ref, sharedPreferences: sharedPrefs);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -24,15 +24,12 @@ List<Widget> buildClientSettingsTheme(BuildContext context, WidgetRef ref) {
|
|||
items: ThemeMode.values,
|
||||
selected: [ref.read(clientSettingsProvider.select((value) => value.themeMode))],
|
||||
onChanged: (values) => ref.read(clientSettingsProvider.notifier).setThemeMode(values.first),
|
||||
itemBuilder: (type, selected, tap) => RadioGroup(
|
||||
groupValue: ref.read(clientSettingsProvider.select((value) => value.themeMode)),
|
||||
itemBuilder: (type, selected, tap) => CheckboxListTile(
|
||||
value: selected,
|
||||
onChanged: (value) => tap(),
|
||||
child: RadioListTile(
|
||||
value: type,
|
||||
title: Text(type.label(context)),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||
),
|
||||
title: Text(type.label(context)),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -41,43 +38,40 @@ List<Widget> buildClientSettingsTheme(BuildContext context, WidgetRef ref) {
|
|||
subLabel: Text(clientSettings.themeColor?.name ?? context.localized.dynamicText),
|
||||
onTap: () => openMultiSelectOptions<ColorThemes?>(
|
||||
context,
|
||||
label: context.localized.settingsLayoutModesTitle,
|
||||
label: context.localized.color,
|
||||
items: [null, ...ColorThemes.values],
|
||||
selected: [(ref.read(clientSettingsProvider.select((value) => value.themeColor)))],
|
||||
onChanged: (values) => ref.read(clientSettingsProvider.notifier).setThemeColor(values.first),
|
||||
itemBuilder: (type, selected, tap) => RadioGroup(
|
||||
itemBuilder: (type, selected, tap) => CheckboxListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: selected,
|
||||
onChanged: (value) => tap(),
|
||||
groupValue: ref.read(clientSettingsProvider.select((value) => value.themeColor)),
|
||||
child: RadioListTile<ColorThemes?>(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: type,
|
||||
title: Row(
|
||||
children: [
|
||||
Container(
|
||||
height: 24,
|
||||
width: 24,
|
||||
decoration: BoxDecoration(
|
||||
gradient: type == null
|
||||
? const SweepGradient(
|
||||
center: FractionalOffset.center,
|
||||
colors: <Color>[
|
||||
Color(0xFF4285F4), // blue
|
||||
Color(0xFF34A853), // green
|
||||
Color(0xFFFBBC05), // yellow
|
||||
Color(0xFFEA4335), // red
|
||||
Color(0xFF4285F4), // blue again to seamlessly transition to the start
|
||||
],
|
||||
stops: <double>[0.0, 0.25, 0.5, 0.75, 1.0],
|
||||
)
|
||||
: null,
|
||||
color: type?.color,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
title: Row(
|
||||
children: [
|
||||
Container(
|
||||
height: 24,
|
||||
width: 24,
|
||||
decoration: BoxDecoration(
|
||||
gradient: type == null
|
||||
? const SweepGradient(
|
||||
center: FractionalOffset.center,
|
||||
colors: <Color>[
|
||||
Color(0xFF4285F4), // blue
|
||||
Color(0xFF34A853), // green
|
||||
Color(0xFFFBBC05), // yellow
|
||||
Color(0xFFEA4335), // red
|
||||
Color(0xFF4285F4), // blue again to seamlessly transition to the start
|
||||
],
|
||||
stops: <double>[0.0, 0.25, 0.5, 0.75, 1.0],
|
||||
)
|
||||
: null,
|
||||
color: type?.color,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(type?.name ?? context.localized.dynamicText),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(type?.name ?? context.localized.dynamicText),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -88,18 +82,15 @@ List<Widget> buildClientSettingsTheme(BuildContext context, WidgetRef ref) {
|
|||
onTap: () async {
|
||||
await openMultiSelectOptions<DynamicSchemeVariant>(
|
||||
context,
|
||||
label: context.localized.settingsLayoutModesTitle,
|
||||
label: context.localized.clientSettingsSchemeVariantTitle,
|
||||
items: DynamicSchemeVariant.values,
|
||||
selected: [(ref.read(clientSettingsProvider.select((value) => value.schemeVariant)))],
|
||||
onChanged: (values) => ref.read(clientSettingsProvider.notifier).setSchemeVariant(values.first),
|
||||
itemBuilder: (type, selected, tap) => RadioGroup(
|
||||
itemBuilder: (type, selected, tap) => CheckboxListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: selected,
|
||||
onChanged: (value) => tap(),
|
||||
groupValue: selected ? type : null,
|
||||
child: RadioListTile<DynamicSchemeVariant>(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: type,
|
||||
title: Text(type.label(context)),
|
||||
),
|
||||
title: Text(type.label(context)),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class PlayerSettings {
|
|||
PlayerSettings({
|
||||
required this.enableTunneling,
|
||||
required this.skipTypes,
|
||||
this.themeColor,
|
||||
required this.skipForward,
|
||||
required this.skipBackward,
|
||||
});
|
||||
|
|
@ -55,6 +56,8 @@ class PlayerSettings {
|
|||
|
||||
Map<SegmentType, SegmentSkip> skipTypes;
|
||||
|
||||
int? themeColor;
|
||||
|
||||
int skipForward;
|
||||
|
||||
int skipBackward;
|
||||
|
|
@ -63,6 +66,7 @@ class PlayerSettings {
|
|||
return <Object?>[
|
||||
enableTunneling,
|
||||
skipTypes,
|
||||
themeColor,
|
||||
skipForward,
|
||||
skipBackward,
|
||||
];
|
||||
|
|
@ -76,8 +80,9 @@ class PlayerSettings {
|
|||
return PlayerSettings(
|
||||
enableTunneling: result[0]! as bool,
|
||||
skipTypes: (result[1] as Map<Object?, Object?>?)!.cast<SegmentType, SegmentSkip>(),
|
||||
skipForward: result[2]! as int,
|
||||
skipBackward: result[3]! as int,
|
||||
themeColor: result[2] as int?,
|
||||
skipForward: result[3]! as int,
|
||||
skipBackward: result[4]! as int,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ Future<List<T>> openMultiSelectOptions<T>(
|
|||
builder: (context, setState) => AlertDialog(
|
||||
title: Text(label),
|
||||
content: SizedBox(
|
||||
width: MediaQuery.of(context).size.width * 0.65,
|
||||
width: MediaQuery.of(context).size.width * 0.85,
|
||||
child: ListView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue