mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-08 23:18:16 -07:00
feature: Added settings to force the player into certain orientations (#108)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
691293648b
commit
c32f71b368
11 changed files with 170 additions and 5 deletions
|
|
@ -1099,5 +1099,11 @@
|
||||||
"deleteFilterConfirmation": "Are you sure you want to delete this filter?",
|
"deleteFilterConfirmation": "Are you sure you want to delete this filter?",
|
||||||
"libraryFiltersLimitReached" : "Filter limit reached (10) remove some filters",
|
"libraryFiltersLimitReached" : "Filter limit reached (10) remove some filters",
|
||||||
"libraryFiltersRemoveAll": "Remove all filters",
|
"libraryFiltersRemoveAll": "Remove all filters",
|
||||||
"libraryFiltersRemoveAllConfirm": "This will delete all saved filters for every library"
|
"libraryFiltersRemoveAllConfirm": "This will delete all saved filters for every library",
|
||||||
|
"playerSettingsOrientationTitle": "Player orientation",
|
||||||
|
"playerSettingsOrientationDesc": "Force the video player into certain orientations",
|
||||||
|
"deviceOrientationPortraitUp": "Portrait Up",
|
||||||
|
"deviceOrientationPortraitDown": "Portrait Down",
|
||||||
|
"deviceOrientationLandscapeLeft": "Landscape Left",
|
||||||
|
"deviceOrientationLandscapeRight": "Landscape Right"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
@ -20,6 +21,7 @@ class VideoPlayerSettingsModel with _$VideoPlayerSettingsModel {
|
||||||
@Default(true) bool hardwareAccel,
|
@Default(true) bool hardwareAccel,
|
||||||
@Default(false) bool useLibass,
|
@Default(false) bool useLibass,
|
||||||
@Default(100) double internalVolume,
|
@Default(100) double internalVolume,
|
||||||
|
Set<DeviceOrientation>? allowedOrientations,
|
||||||
@Default(AutoNextType.static) AutoNextType nextVideoType,
|
@Default(AutoNextType.static) AutoNextType nextVideoType,
|
||||||
String? audioDevice,
|
String? audioDevice,
|
||||||
}) = _VideoPlayerSettingsModel;
|
}) = _VideoPlayerSettingsModel;
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ mixin _$VideoPlayerSettingsModel {
|
||||||
bool get hardwareAccel => throw _privateConstructorUsedError;
|
bool get hardwareAccel => throw _privateConstructorUsedError;
|
||||||
bool get useLibass => throw _privateConstructorUsedError;
|
bool get useLibass => throw _privateConstructorUsedError;
|
||||||
double get internalVolume => throw _privateConstructorUsedError;
|
double get internalVolume => throw _privateConstructorUsedError;
|
||||||
|
Set<DeviceOrientation>? get allowedOrientations =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
AutoNextType get nextVideoType => throw _privateConstructorUsedError;
|
AutoNextType get nextVideoType => throw _privateConstructorUsedError;
|
||||||
String? get audioDevice => throw _privateConstructorUsedError;
|
String? get audioDevice => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
|
@ -53,6 +55,7 @@ abstract class $VideoPlayerSettingsModelCopyWith<$Res> {
|
||||||
bool hardwareAccel,
|
bool hardwareAccel,
|
||||||
bool useLibass,
|
bool useLibass,
|
||||||
double internalVolume,
|
double internalVolume,
|
||||||
|
Set<DeviceOrientation>? allowedOrientations,
|
||||||
AutoNextType nextVideoType,
|
AutoNextType nextVideoType,
|
||||||
String? audioDevice});
|
String? audioDevice});
|
||||||
}
|
}
|
||||||
|
|
@ -79,6 +82,7 @@ class _$VideoPlayerSettingsModelCopyWithImpl<$Res,
|
||||||
Object? hardwareAccel = null,
|
Object? hardwareAccel = null,
|
||||||
Object? useLibass = null,
|
Object? useLibass = null,
|
||||||
Object? internalVolume = null,
|
Object? internalVolume = null,
|
||||||
|
Object? allowedOrientations = freezed,
|
||||||
Object? nextVideoType = null,
|
Object? nextVideoType = null,
|
||||||
Object? audioDevice = freezed,
|
Object? audioDevice = freezed,
|
||||||
}) {
|
}) {
|
||||||
|
|
@ -107,6 +111,10 @@ class _$VideoPlayerSettingsModelCopyWithImpl<$Res,
|
||||||
? _value.internalVolume
|
? _value.internalVolume
|
||||||
: internalVolume // ignore: cast_nullable_to_non_nullable
|
: internalVolume // ignore: cast_nullable_to_non_nullable
|
||||||
as double,
|
as double,
|
||||||
|
allowedOrientations: freezed == allowedOrientations
|
||||||
|
? _value.allowedOrientations
|
||||||
|
: allowedOrientations // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Set<DeviceOrientation>?,
|
||||||
nextVideoType: null == nextVideoType
|
nextVideoType: null == nextVideoType
|
||||||
? _value.nextVideoType
|
? _value.nextVideoType
|
||||||
: nextVideoType // ignore: cast_nullable_to_non_nullable
|
: nextVideoType // ignore: cast_nullable_to_non_nullable
|
||||||
|
|
@ -135,6 +143,7 @@ abstract class _$$VideoPlayerSettingsModelImplCopyWith<$Res>
|
||||||
bool hardwareAccel,
|
bool hardwareAccel,
|
||||||
bool useLibass,
|
bool useLibass,
|
||||||
double internalVolume,
|
double internalVolume,
|
||||||
|
Set<DeviceOrientation>? allowedOrientations,
|
||||||
AutoNextType nextVideoType,
|
AutoNextType nextVideoType,
|
||||||
String? audioDevice});
|
String? audioDevice});
|
||||||
}
|
}
|
||||||
|
|
@ -160,6 +169,7 @@ class __$$VideoPlayerSettingsModelImplCopyWithImpl<$Res>
|
||||||
Object? hardwareAccel = null,
|
Object? hardwareAccel = null,
|
||||||
Object? useLibass = null,
|
Object? useLibass = null,
|
||||||
Object? internalVolume = null,
|
Object? internalVolume = null,
|
||||||
|
Object? allowedOrientations = freezed,
|
||||||
Object? nextVideoType = null,
|
Object? nextVideoType = null,
|
||||||
Object? audioDevice = freezed,
|
Object? audioDevice = freezed,
|
||||||
}) {
|
}) {
|
||||||
|
|
@ -188,6 +198,10 @@ class __$$VideoPlayerSettingsModelImplCopyWithImpl<$Res>
|
||||||
? _value.internalVolume
|
? _value.internalVolume
|
||||||
: internalVolume // ignore: cast_nullable_to_non_nullable
|
: internalVolume // ignore: cast_nullable_to_non_nullable
|
||||||
as double,
|
as double,
|
||||||
|
allowedOrientations: freezed == allowedOrientations
|
||||||
|
? _value._allowedOrientations
|
||||||
|
: allowedOrientations // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Set<DeviceOrientation>?,
|
||||||
nextVideoType: null == nextVideoType
|
nextVideoType: null == nextVideoType
|
||||||
? _value.nextVideoType
|
? _value.nextVideoType
|
||||||
: nextVideoType // ignore: cast_nullable_to_non_nullable
|
: nextVideoType // ignore: cast_nullable_to_non_nullable
|
||||||
|
|
@ -211,9 +225,11 @@ class _$VideoPlayerSettingsModelImpl extends _VideoPlayerSettingsModel
|
||||||
this.hardwareAccel = true,
|
this.hardwareAccel = true,
|
||||||
this.useLibass = false,
|
this.useLibass = false,
|
||||||
this.internalVolume = 100,
|
this.internalVolume = 100,
|
||||||
|
final Set<DeviceOrientation>? allowedOrientations,
|
||||||
this.nextVideoType = AutoNextType.static,
|
this.nextVideoType = AutoNextType.static,
|
||||||
this.audioDevice})
|
this.audioDevice})
|
||||||
: super._();
|
: _allowedOrientations = allowedOrientations,
|
||||||
|
super._();
|
||||||
|
|
||||||
factory _$VideoPlayerSettingsModelImpl.fromJson(Map<String, dynamic> json) =>
|
factory _$VideoPlayerSettingsModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
_$$VideoPlayerSettingsModelImplFromJson(json);
|
_$$VideoPlayerSettingsModelImplFromJson(json);
|
||||||
|
|
@ -235,6 +251,17 @@ class _$VideoPlayerSettingsModelImpl extends _VideoPlayerSettingsModel
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final double internalVolume;
|
final double internalVolume;
|
||||||
|
final Set<DeviceOrientation>? _allowedOrientations;
|
||||||
|
@override
|
||||||
|
Set<DeviceOrientation>? get allowedOrientations {
|
||||||
|
final value = _allowedOrientations;
|
||||||
|
if (value == null) return null;
|
||||||
|
if (_allowedOrientations is EqualUnmodifiableSetView)
|
||||||
|
return _allowedOrientations;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableSetView(value);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final AutoNextType nextVideoType;
|
final AutoNextType nextVideoType;
|
||||||
|
|
@ -243,7 +270,7 @@ class _$VideoPlayerSettingsModelImpl extends _VideoPlayerSettingsModel
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
|
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
|
||||||
return 'VideoPlayerSettingsModel(screenBrightness: $screenBrightness, videoFit: $videoFit, fillScreen: $fillScreen, hardwareAccel: $hardwareAccel, useLibass: $useLibass, internalVolume: $internalVolume, nextVideoType: $nextVideoType, audioDevice: $audioDevice)';
|
return 'VideoPlayerSettingsModel(screenBrightness: $screenBrightness, videoFit: $videoFit, fillScreen: $fillScreen, hardwareAccel: $hardwareAccel, useLibass: $useLibass, internalVolume: $internalVolume, allowedOrientations: $allowedOrientations, nextVideoType: $nextVideoType, audioDevice: $audioDevice)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -257,6 +284,7 @@ class _$VideoPlayerSettingsModelImpl extends _VideoPlayerSettingsModel
|
||||||
..add(DiagnosticsProperty('hardwareAccel', hardwareAccel))
|
..add(DiagnosticsProperty('hardwareAccel', hardwareAccel))
|
||||||
..add(DiagnosticsProperty('useLibass', useLibass))
|
..add(DiagnosticsProperty('useLibass', useLibass))
|
||||||
..add(DiagnosticsProperty('internalVolume', internalVolume))
|
..add(DiagnosticsProperty('internalVolume', internalVolume))
|
||||||
|
..add(DiagnosticsProperty('allowedOrientations', allowedOrientations))
|
||||||
..add(DiagnosticsProperty('nextVideoType', nextVideoType))
|
..add(DiagnosticsProperty('nextVideoType', nextVideoType))
|
||||||
..add(DiagnosticsProperty('audioDevice', audioDevice));
|
..add(DiagnosticsProperty('audioDevice', audioDevice));
|
||||||
}
|
}
|
||||||
|
|
@ -286,6 +314,7 @@ abstract class _VideoPlayerSettingsModel extends VideoPlayerSettingsModel {
|
||||||
final bool hardwareAccel,
|
final bool hardwareAccel,
|
||||||
final bool useLibass,
|
final bool useLibass,
|
||||||
final double internalVolume,
|
final double internalVolume,
|
||||||
|
final Set<DeviceOrientation>? allowedOrientations,
|
||||||
final AutoNextType nextVideoType,
|
final AutoNextType nextVideoType,
|
||||||
final String? audioDevice}) = _$VideoPlayerSettingsModelImpl;
|
final String? audioDevice}) = _$VideoPlayerSettingsModelImpl;
|
||||||
_VideoPlayerSettingsModel._() : super._();
|
_VideoPlayerSettingsModel._() : super._();
|
||||||
|
|
@ -306,6 +335,8 @@ abstract class _VideoPlayerSettingsModel extends VideoPlayerSettingsModel {
|
||||||
@override
|
@override
|
||||||
double get internalVolume;
|
double get internalVolume;
|
||||||
@override
|
@override
|
||||||
|
Set<DeviceOrientation>? get allowedOrientations;
|
||||||
|
@override
|
||||||
AutoNextType get nextVideoType;
|
AutoNextType get nextVideoType;
|
||||||
@override
|
@override
|
||||||
String? get audioDevice;
|
String? get audioDevice;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@ _$VideoPlayerSettingsModelImpl _$$VideoPlayerSettingsModelImplFromJson(
|
||||||
hardwareAccel: json['hardwareAccel'] as bool? ?? true,
|
hardwareAccel: json['hardwareAccel'] as bool? ?? true,
|
||||||
useLibass: json['useLibass'] as bool? ?? false,
|
useLibass: json['useLibass'] as bool? ?? false,
|
||||||
internalVolume: (json['internalVolume'] as num?)?.toDouble() ?? 100,
|
internalVolume: (json['internalVolume'] as num?)?.toDouble() ?? 100,
|
||||||
|
allowedOrientations: (json['allowedOrientations'] as List<dynamic>?)
|
||||||
|
?.map((e) => $enumDecode(_$DeviceOrientationEnumMap, e))
|
||||||
|
.toSet(),
|
||||||
nextVideoType:
|
nextVideoType:
|
||||||
$enumDecodeNullable(_$AutoNextTypeEnumMap, json['nextVideoType']) ??
|
$enumDecodeNullable(_$AutoNextTypeEnumMap, json['nextVideoType']) ??
|
||||||
AutoNextType.static,
|
AutoNextType.static,
|
||||||
|
|
@ -31,6 +34,9 @@ Map<String, dynamic> _$$VideoPlayerSettingsModelImplToJson(
|
||||||
'hardwareAccel': instance.hardwareAccel,
|
'hardwareAccel': instance.hardwareAccel,
|
||||||
'useLibass': instance.useLibass,
|
'useLibass': instance.useLibass,
|
||||||
'internalVolume': instance.internalVolume,
|
'internalVolume': instance.internalVolume,
|
||||||
|
'allowedOrientations': instance.allowedOrientations
|
||||||
|
?.map((e) => _$DeviceOrientationEnumMap[e]!)
|
||||||
|
.toList(),
|
||||||
'nextVideoType': _$AutoNextTypeEnumMap[instance.nextVideoType]!,
|
'nextVideoType': _$AutoNextTypeEnumMap[instance.nextVideoType]!,
|
||||||
'audioDevice': instance.audioDevice,
|
'audioDevice': instance.audioDevice,
|
||||||
};
|
};
|
||||||
|
|
@ -45,6 +51,13 @@ const _$BoxFitEnumMap = {
|
||||||
BoxFit.scaleDown: 'scaleDown',
|
BoxFit.scaleDown: 'scaleDown',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const _$DeviceOrientationEnumMap = {
|
||||||
|
DeviceOrientation.portraitUp: 'portraitUp',
|
||||||
|
DeviceOrientation.landscapeLeft: 'landscapeLeft',
|
||||||
|
DeviceOrientation.portraitDown: 'portraitDown',
|
||||||
|
DeviceOrientation.landscapeRight: 'landscapeRight',
|
||||||
|
};
|
||||||
|
|
||||||
const _$AutoNextTypeEnumMap = {
|
const _$AutoNextTypeEnumMap = {
|
||||||
AutoNextType.off: 'off',
|
AutoNextType.off: 'off',
|
||||||
AutoNextType.smart: 'smart',
|
AutoNextType.smart: 'smart',
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ part of 'library_filters_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$libraryFiltersHash() => r'7b4661651df7e0c019dca5bb7eb6433bcd8b3ebb';
|
String _$libraryFiltersHash() => r'fd98699d8d7c1db6daefa6e53d5d90f989a8f776';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:screen_brightness/screen_brightness.dart';
|
import 'package:screen_brightness/screen_brightness.dart';
|
||||||
|
|
@ -63,4 +64,7 @@ class VideoPlayerSettingsProviderNotifier extends StateNotifier<VideoPlayerSetti
|
||||||
state = state.copyWith(internalVolume: value);
|
state = state.copyWith(internalVolume: value);
|
||||||
ref.read(videoPlayerProvider).setVolume(value);
|
ref.read(videoPlayerProvider).setVolume(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void toggleOrientation(Set<DeviceOrientation>? orientation) =>
|
||||||
|
state = state.copyWith(allowedOrientations: orientation);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ final showSyncButtonProviderProvider = AutoDisposeProvider<bool>.internal(
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef ShowSyncButtonProviderRef = AutoDisposeProviderRef<bool>;
|
typedef ShowSyncButtonProviderRef = AutoDisposeProviderRef<bool>;
|
||||||
String _$userHash() => r'418b3d4ade830479db9f48c7793ac5b646778b82';
|
String _$userHash() => r'e83369c0d569d5a862aa1b92f3f0a45a9d1fe446';
|
||||||
|
|
||||||
/// See also [User].
|
/// See also [User].
|
||||||
@ProviderFor(User)
|
@ProviderFor(User)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import 'package:fladder/screens/settings/widgets/settings_label_divider.dart';
|
||||||
import 'package:fladder/screens/settings/widgets/settings_message_box.dart';
|
import 'package:fladder/screens/settings/widgets/settings_message_box.dart';
|
||||||
import 'package:fladder/screens/settings/widgets/subtitle_editor.dart';
|
import 'package:fladder/screens/settings/widgets/subtitle_editor.dart';
|
||||||
import 'package:fladder/screens/shared/animated_fade_size.dart';
|
import 'package:fladder/screens/shared/animated_fade_size.dart';
|
||||||
|
import 'package:fladder/screens/video_player/components/video_player_options_sheet.dart';
|
||||||
import 'package:fladder/util/adaptive_layout.dart';
|
import 'package:fladder/util/adaptive_layout.dart';
|
||||||
import 'package:fladder/util/box_fit_extension.dart';
|
import 'package:fladder/util/box_fit_extension.dart';
|
||||||
import 'package:fladder/util/localization_helper.dart';
|
import 'package:fladder/util/localization_helper.dart';
|
||||||
|
|
@ -151,6 +152,12 @@ class _PlayerSettingsPageState extends ConsumerState<PlayerSettingsPage> {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
if (!AdaptiveLayout.of(context).isDesktop && !kIsWeb)
|
||||||
|
SettingsListTile(
|
||||||
|
label: Text(context.localized.playerSettingsOrientationTitle),
|
||||||
|
subLabel: Text(context.localized.playerSettingsOrientationDesc),
|
||||||
|
onTap: () => showOrientationOptions(context, ref),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:ficonsax/ficonsax.dart';
|
import 'package:ficonsax/ficonsax.dart';
|
||||||
|
|
@ -19,6 +21,7 @@ import 'package:fladder/screens/playlists/add_to_playlists.dart';
|
||||||
import 'package:fladder/screens/video_player/components/video_player_queue.dart';
|
import 'package:fladder/screens/video_player/components/video_player_queue.dart';
|
||||||
import 'package:fladder/screens/video_player/components/video_subtitle_controls.dart';
|
import 'package:fladder/screens/video_player/components/video_subtitle_controls.dart';
|
||||||
import 'package:fladder/util/adaptive_layout.dart';
|
import 'package:fladder/util/adaptive_layout.dart';
|
||||||
|
import 'package:fladder/util/device_orientation_extension.dart';
|
||||||
import 'package:fladder/util/list_padding.dart';
|
import 'package:fladder/util/list_padding.dart';
|
||||||
import 'package:fladder/util/localization_helper.dart';
|
import 'package:fladder/util/localization_helper.dart';
|
||||||
import 'package:fladder/util/refresh_state.dart';
|
import 'package:fladder/util/refresh_state.dart';
|
||||||
|
|
@ -176,6 +179,11 @@ class _VideoOptionsMobileState extends ConsumerState<VideoOptions> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (!AdaptiveLayout.of(context).isDesktop && !kIsWeb)
|
||||||
|
SpacedListTile(
|
||||||
|
title: Text(context.localized.playerSettingsOrientationTitle),
|
||||||
|
onTap: () => showOrientationOptions(context, ref),
|
||||||
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
|
@ -492,3 +500,70 @@ Future<void> showPlaybackSpeed(BuildContext context) {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> showOrientationOptions(BuildContext context, WidgetRef ref) async {
|
||||||
|
Set<DeviceOrientation> orientations = ref
|
||||||
|
.read(videoPlayerSettingsProvider
|
||||||
|
.select((value) => value.allowedOrientations ?? Set.from(DeviceOrientation.values)))
|
||||||
|
.toSet();
|
||||||
|
|
||||||
|
void toggleOrientation(DeviceOrientation orientation) {
|
||||||
|
if (orientations.contains(orientation) && orientations.length > 1) {
|
||||||
|
orientations.remove(orientation);
|
||||||
|
} else {
|
||||||
|
orientations.add(orientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return StatefulBuilder(builder: (context, state) {
|
||||||
|
return SimpleDialog(
|
||||||
|
contentPadding: const EdgeInsets.only(top: 8, bottom: 24),
|
||||||
|
title: Row(children: [Text(context.localized.playbackRate)]),
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12).copyWith(top: 6),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Divider(),
|
||||||
|
...DeviceOrientation.values.map(
|
||||||
|
(orientation) => CheckboxListTile.adaptive(
|
||||||
|
title: Text(orientation.label(context)),
|
||||||
|
value: orientations.contains(orientation),
|
||||||
|
onChanged: (value) {
|
||||||
|
state(() => toggleOrientation(orientation));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text(context.localized.cancel),
|
||||||
|
),
|
||||||
|
FilledButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
ref.read(videoPlayerSettingsProvider.notifier).toggleOrientation(orientations);
|
||||||
|
},
|
||||||
|
child: Text(context.localized.save),
|
||||||
|
),
|
||||||
|
].addInBetween(const SizedBox(width: 8)),
|
||||||
|
)
|
||||||
|
].addInBetween(const SizedBox(width: 8)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:media_kit_video/media_kit_video.dart';
|
import 'package:media_kit_video/media_kit_video.dart';
|
||||||
|
|
@ -49,6 +50,7 @@ class _VideoPlayerState extends ConsumerState<VideoPlayer> with WidgetsBindingOb
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
|
SystemChrome.setPreferredOrientations(DeviceOrientation.values);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,6 +60,9 @@ class _VideoPlayerState extends ConsumerState<VideoPlayer> with WidgetsBindingOb
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
Future.microtask(() {
|
Future.microtask(() {
|
||||||
ref.read(mediaPlaybackProvider.notifier).update((state) => state.copyWith(state: VideoPlayerState.fullScreen));
|
ref.read(mediaPlaybackProvider.notifier).update((state) => state.copyWith(state: VideoPlayerState.fullScreen));
|
||||||
|
final orientations = ref.read(videoPlayerSettingsProvider.select((value) => value.allowedOrientations));
|
||||||
|
SystemChrome.setPreferredOrientations(
|
||||||
|
orientations?.isNotEmpty == true ? orientations!.toList() : DeviceOrientation.values);
|
||||||
return ref.read(videoPlayerSettingsProvider.notifier).setSavedBrightness();
|
return ref.read(videoPlayerSettingsProvider.notifier).setSavedBrightness();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -70,6 +75,15 @@ class _VideoPlayerState extends ConsumerState<VideoPlayer> with WidgetsBindingOb
|
||||||
|
|
||||||
final playerController = ref.watch(videoPlayerProvider.select((value) => value.controller));
|
final playerController = ref.watch(videoPlayerProvider.select((value) => value.controller));
|
||||||
|
|
||||||
|
ref.listen(
|
||||||
|
videoPlayerSettingsProvider.select((value) => value.allowedOrientations),
|
||||||
|
(previous, next) {
|
||||||
|
if (previous != next) {
|
||||||
|
SystemChrome.setPreferredOrientations(next?.isNotEmpty == true ? next!.toList() : DeviceOrientation.values);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
return Material(
|
return Material(
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
child: Theme(
|
child: Theme(
|
||||||
|
|
|
||||||
13
lib/util/device_orientation_extension.dart
Normal file
13
lib/util/device_orientation_extension.dart
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'package:fladder/util/localization_helper.dart';
|
||||||
|
|
||||||
|
extension DeviceOrientationExtension on DeviceOrientation {
|
||||||
|
String label(BuildContext context) => switch (this) {
|
||||||
|
DeviceOrientation.portraitUp => context.localized.deviceOrientationPortraitUp,
|
||||||
|
DeviceOrientation.landscapeLeft => context.localized.deviceOrientationLandscapeLeft,
|
||||||
|
DeviceOrientation.portraitDown => context.localized.deviceOrientationPortraitDown,
|
||||||
|
DeviceOrientation.landscapeRight => context.localized.deviceOrientationLandscapeRight,
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue