feat: Customizable shortcuts/hotkeys (#439)

This implements the logic for allowing hotkeys with modifiers.
Implemented globalhotkeys and videocontrol hotkeys
Also implements saving the forward backwards seconds to the user.

Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
PartyDonut 2025-08-08 16:36:50 +02:00 committed by GitHub
parent 23385d8e62
commit fa30e634b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 1360 additions and 162 deletions

View file

@ -3,17 +3,35 @@ import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:fladder/models/settings/key_combinations.dart';
import 'package:fladder/util/custom_color_themes.dart';
import 'package:fladder/util/localization_helper.dart';
part 'client_settings_model.freezed.dart';
part 'client_settings_model.g.dart';
enum GlobalHotKeys {
search,
exit;
const GlobalHotKeys();
String label(BuildContext context) {
return switch (this) {
GlobalHotKeys.search => context.localized.search,
GlobalHotKeys.exit => context.localized.exitFladderTitle,
};
}
}
@Freezed(copyWith: true)
class ClientSettingsModel with _$ClientSettingsModel {
const ClientSettingsModel._();
factory ClientSettingsModel({
String? syncPath,
@Default(Vector2(x: 0, y: 0)) Vector2 position,
@ -39,10 +57,16 @@ class ClientSettingsModel with _$ClientSettingsModel {
@Default(false) bool usePosterForLibrary,
String? lastViewedUpdate,
int? libraryPageSize,
@Default({}) Map<GlobalHotKeys, KeyCombination?> shortcuts,
}) = _ClientSettingsModel;
factory ClientSettingsModel.fromJson(Map<String, dynamic> json) => _$ClientSettingsModelFromJson(json);
Map<GlobalHotKeys, KeyCombination> get currentShortcuts =>
_defaultGlobalHotKeys.map((key, value) => MapEntry(key, shortcuts[key] ?? value));
Map<GlobalHotKeys, KeyCombination> get defaultShortCuts => _defaultGlobalHotKeys;
Brightness statusBarBrightness(BuildContext context) {
return switch (themeMode) {
ThemeMode.dark => Brightness.light,
@ -132,3 +156,12 @@ class Vector2 {
static Vector2 fromPosition(Offset windowPosition) => Vector2(x: windowPosition.dx, y: windowPosition.dy);
}
Map<GlobalHotKeys, KeyCombination> get _defaultGlobalHotKeys => {
for (var hotKey in GlobalHotKeys.values)
hotKey: switch (hotKey) {
GlobalHotKeys.search =>
KeyCombination(key: LogicalKeyboardKey.keyK, modifier: LogicalKeyboardKey.controlLeft),
GlobalHotKeys.exit => KeyCombination(key: LogicalKeyboardKey.keyQ, modifier: LogicalKeyboardKey.controlLeft),
},
};

View file

@ -45,6 +45,8 @@ mixin _$ClientSettingsModel {
bool get usePosterForLibrary => throw _privateConstructorUsedError;
String? get lastViewedUpdate => throw _privateConstructorUsedError;
int? get libraryPageSize => throw _privateConstructorUsedError;
Map<GlobalHotKeys, KeyCombination?> get shortcuts =>
throw _privateConstructorUsedError;
/// Serializes this ClientSettingsModel to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@ -86,7 +88,8 @@ abstract class $ClientSettingsModelCopyWith<$Res> {
bool checkForUpdates,
bool usePosterForLibrary,
String? lastViewedUpdate,
int? libraryPageSize});
int? libraryPageSize,
Map<GlobalHotKeys, KeyCombination?> shortcuts});
}
/// @nodoc
@ -128,6 +131,7 @@ class _$ClientSettingsModelCopyWithImpl<$Res, $Val extends ClientSettingsModel>
Object? usePosterForLibrary = null,
Object? lastViewedUpdate = freezed,
Object? libraryPageSize = freezed,
Object? shortcuts = null,
}) {
return _then(_value.copyWith(
syncPath: freezed == syncPath
@ -226,6 +230,10 @@ class _$ClientSettingsModelCopyWithImpl<$Res, $Val extends ClientSettingsModel>
? _value.libraryPageSize
: libraryPageSize // ignore: cast_nullable_to_non_nullable
as int?,
shortcuts: null == shortcuts
? _value.shortcuts
: shortcuts // ignore: cast_nullable_to_non_nullable
as Map<GlobalHotKeys, KeyCombination?>,
) as $Val);
}
}
@ -262,7 +270,8 @@ abstract class _$$ClientSettingsModelImplCopyWith<$Res>
bool checkForUpdates,
bool usePosterForLibrary,
String? lastViewedUpdate,
int? libraryPageSize});
int? libraryPageSize,
Map<GlobalHotKeys, KeyCombination?> shortcuts});
}
/// @nodoc
@ -302,6 +311,7 @@ class __$$ClientSettingsModelImplCopyWithImpl<$Res>
Object? usePosterForLibrary = null,
Object? lastViewedUpdate = freezed,
Object? libraryPageSize = freezed,
Object? shortcuts = null,
}) {
return _then(_$ClientSettingsModelImpl(
syncPath: freezed == syncPath
@ -400,6 +410,10 @@ class __$$ClientSettingsModelImplCopyWithImpl<$Res>
? _value.libraryPageSize
: libraryPageSize // ignore: cast_nullable_to_non_nullable
as int?,
shortcuts: null == shortcuts
? _value._shortcuts
: shortcuts // ignore: cast_nullable_to_non_nullable
as Map<GlobalHotKeys, KeyCombination?>,
));
}
}
@ -432,8 +446,10 @@ class _$ClientSettingsModelImpl extends _ClientSettingsModel
this.checkForUpdates = true,
this.usePosterForLibrary = false,
this.lastViewedUpdate,
this.libraryPageSize})
: super._();
this.libraryPageSize,
final Map<GlobalHotKeys, KeyCombination?> shortcuts = const {}})
: _shortcuts = shortcuts,
super._();
factory _$ClientSettingsModelImpl.fromJson(Map<String, dynamic> json) =>
_$$ClientSettingsModelImplFromJson(json);
@ -505,10 +521,18 @@ class _$ClientSettingsModelImpl extends _ClientSettingsModel
final String? lastViewedUpdate;
@override
final int? libraryPageSize;
final Map<GlobalHotKeys, KeyCombination?> _shortcuts;
@override
@JsonKey()
Map<GlobalHotKeys, KeyCombination?> get shortcuts {
if (_shortcuts is EqualUnmodifiableMapView) return _shortcuts;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(_shortcuts);
}
@override
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
return 'ClientSettingsModel(syncPath: $syncPath, position: $position, size: $size, timeOut: $timeOut, nextUpDateCutoff: $nextUpDateCutoff, themeMode: $themeMode, themeColor: $themeColor, amoledBlack: $amoledBlack, blurPlaceHolders: $blurPlaceHolders, blurUpcomingEpisodes: $blurUpcomingEpisodes, selectedLocale: $selectedLocale, enableMediaKeys: $enableMediaKeys, posterSize: $posterSize, pinchPosterZoom: $pinchPosterZoom, mouseDragSupport: $mouseDragSupport, requireWifi: $requireWifi, showAllCollectionTypes: $showAllCollectionTypes, maxConcurrentDownloads: $maxConcurrentDownloads, schemeVariant: $schemeVariant, backgroundPosters: $backgroundPosters, checkForUpdates: $checkForUpdates, usePosterForLibrary: $usePosterForLibrary, lastViewedUpdate: $lastViewedUpdate, libraryPageSize: $libraryPageSize)';
return 'ClientSettingsModel(syncPath: $syncPath, position: $position, size: $size, timeOut: $timeOut, nextUpDateCutoff: $nextUpDateCutoff, themeMode: $themeMode, themeColor: $themeColor, amoledBlack: $amoledBlack, blurPlaceHolders: $blurPlaceHolders, blurUpcomingEpisodes: $blurUpcomingEpisodes, selectedLocale: $selectedLocale, enableMediaKeys: $enableMediaKeys, posterSize: $posterSize, pinchPosterZoom: $pinchPosterZoom, mouseDragSupport: $mouseDragSupport, requireWifi: $requireWifi, showAllCollectionTypes: $showAllCollectionTypes, maxConcurrentDownloads: $maxConcurrentDownloads, schemeVariant: $schemeVariant, backgroundPosters: $backgroundPosters, checkForUpdates: $checkForUpdates, usePosterForLibrary: $usePosterForLibrary, lastViewedUpdate: $lastViewedUpdate, libraryPageSize: $libraryPageSize, shortcuts: $shortcuts)';
}
@override
@ -541,7 +565,8 @@ class _$ClientSettingsModelImpl extends _ClientSettingsModel
..add(DiagnosticsProperty('checkForUpdates', checkForUpdates))
..add(DiagnosticsProperty('usePosterForLibrary', usePosterForLibrary))
..add(DiagnosticsProperty('lastViewedUpdate', lastViewedUpdate))
..add(DiagnosticsProperty('libraryPageSize', libraryPageSize));
..add(DiagnosticsProperty('libraryPageSize', libraryPageSize))
..add(DiagnosticsProperty('shortcuts', shortcuts));
}
/// Create a copy of ClientSettingsModel
@ -563,30 +588,32 @@ class _$ClientSettingsModelImpl extends _ClientSettingsModel
abstract class _ClientSettingsModel extends ClientSettingsModel {
factory _ClientSettingsModel(
{final String? syncPath,
final Vector2 position,
final Vector2 size,
final Duration? timeOut,
final Duration? nextUpDateCutoff,
final ThemeMode themeMode,
final ColorThemes? themeColor,
final bool amoledBlack,
final bool blurPlaceHolders,
final bool blurUpcomingEpisodes,
@LocaleConvert() final Locale? selectedLocale,
final bool enableMediaKeys,
final double posterSize,
final bool pinchPosterZoom,
final bool mouseDragSupport,
final bool requireWifi,
final bool showAllCollectionTypes,
final int maxConcurrentDownloads,
final DynamicSchemeVariant schemeVariant,
final bool backgroundPosters,
final bool checkForUpdates,
final bool usePosterForLibrary,
final String? lastViewedUpdate,
final int? libraryPageSize}) = _$ClientSettingsModelImpl;
{final String? syncPath,
final Vector2 position,
final Vector2 size,
final Duration? timeOut,
final Duration? nextUpDateCutoff,
final ThemeMode themeMode,
final ColorThemes? themeColor,
final bool amoledBlack,
final bool blurPlaceHolders,
final bool blurUpcomingEpisodes,
@LocaleConvert() final Locale? selectedLocale,
final bool enableMediaKeys,
final double posterSize,
final bool pinchPosterZoom,
final bool mouseDragSupport,
final bool requireWifi,
final bool showAllCollectionTypes,
final int maxConcurrentDownloads,
final DynamicSchemeVariant schemeVariant,
final bool backgroundPosters,
final bool checkForUpdates,
final bool usePosterForLibrary,
final String? lastViewedUpdate,
final int? libraryPageSize,
final Map<GlobalHotKeys, KeyCombination?> shortcuts}) =
_$ClientSettingsModelImpl;
_ClientSettingsModel._() : super._();
factory _ClientSettingsModel.fromJson(Map<String, dynamic> json) =
@ -641,6 +668,8 @@ abstract class _ClientSettingsModel extends ClientSettingsModel {
String? get lastViewedUpdate;
@override
int? get libraryPageSize;
@override
Map<GlobalHotKeys, KeyCombination?> get shortcuts;
/// Create a copy of ClientSettingsModel
/// with the given fields replaced by the non-null parameter values.

View file

@ -46,6 +46,14 @@ _$ClientSettingsModelImpl _$$ClientSettingsModelImplFromJson(
usePosterForLibrary: json['usePosterForLibrary'] as bool? ?? false,
lastViewedUpdate: json['lastViewedUpdate'] as String?,
libraryPageSize: (json['libraryPageSize'] as num?)?.toInt(),
shortcuts: (json['shortcuts'] as Map<String, dynamic>?)?.map(
(k, e) => MapEntry(
$enumDecode(_$GlobalHotKeysEnumMap, k),
e == null
? null
: KeyCombination.fromJson(e as Map<String, dynamic>)),
) ??
const {},
);
Map<String, dynamic> _$$ClientSettingsModelImplToJson(
@ -75,6 +83,8 @@ Map<String, dynamic> _$$ClientSettingsModelImplToJson(
'usePosterForLibrary': instance.usePosterForLibrary,
'lastViewedUpdate': instance.lastViewedUpdate,
'libraryPageSize': instance.libraryPageSize,
'shortcuts': instance.shortcuts
.map((k, e) => MapEntry(_$GlobalHotKeysEnumMap[k]!, e)),
};
const _$ThemeModeEnumMap = {
@ -112,3 +122,8 @@ const _$DynamicSchemeVariantEnumMap = {
DynamicSchemeVariant.rainbow: 'rainbow',
DynamicSchemeVariant.fruitSalad: 'fruitSalad',
};
const _$GlobalHotKeysEnumMap = {
GlobalHotKeys.search: 'search',
GlobalHotKeys.exit: 'exit',
};

View file

@ -0,0 +1,70 @@
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:fladder/screens/settings/widgets/key_listener.dart';
part 'key_combinations.freezed.dart';
part 'key_combinations.g.dart';
@Freezed(toJson: true, fromJson: true)
class KeyCombination with _$KeyCombination {
const KeyCombination._();
factory KeyCombination({
@LogicalKeyboardSerializer() LogicalKeyboardKey? modifier,
@LogicalKeyboardSerializer() required LogicalKeyboardKey key,
}) = _KeyCombination;
factory KeyCombination.fromJson(Map<String, dynamic> json) => _$KeyCombinationFromJson(json);
@override
bool operator ==(covariant other) {
return other is KeyCombination && other.key.keyId == key.keyId && other.modifier?.keyId == modifier?.keyId;
}
@override
int get hashCode => key.hashCode ^ modifier.hashCode;
String get label => [modifier?.label, key.label].nonNulls.join(" + ");
static final Set<LogicalKeyboardKey> shiftKeys = {
LogicalKeyboardKey.shift,
LogicalKeyboardKey.shiftLeft,
LogicalKeyboardKey.shiftRight,
};
static final altKeys = {
LogicalKeyboardKey.alt,
LogicalKeyboardKey.altRight,
LogicalKeyboardKey.altLeft,
};
static final ctrlKeys = {
LogicalKeyboardKey.control,
LogicalKeyboardKey.controlLeft,
LogicalKeyboardKey.controlRight,
};
static final modifierKeys = {
...shiftKeys,
...altKeys,
...ctrlKeys,
};
}
class LogicalKeyboardSerializer extends JsonConverter<LogicalKeyboardKey, String> {
const LogicalKeyboardSerializer();
@override
LogicalKeyboardKey fromJson(String json) {
return LogicalKeyboardKey.findKeyByKeyId(int.parse(jsonDecode(json))) ?? LogicalKeyboardKey.abort;
}
@override
String toJson(LogicalKeyboardKey object) {
return jsonEncode(object.keyId.toString());
}
}

View file

@ -0,0 +1,79 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'key_combinations.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
KeyCombination _$KeyCombinationFromJson(Map<String, dynamic> json) {
return _KeyCombination.fromJson(json);
}
/// @nodoc
mixin _$KeyCombination {
@LogicalKeyboardSerializer()
LogicalKeyboardKey? get modifier => throw _privateConstructorUsedError;
@LogicalKeyboardSerializer()
LogicalKeyboardKey get key => throw _privateConstructorUsedError;
/// Serializes this KeyCombination to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
}
/// @nodoc
@JsonSerializable()
class _$KeyCombinationImpl extends _KeyCombination {
_$KeyCombinationImpl(
{@LogicalKeyboardSerializer() this.modifier,
@LogicalKeyboardSerializer() required this.key})
: super._();
factory _$KeyCombinationImpl.fromJson(Map<String, dynamic> json) =>
_$$KeyCombinationImplFromJson(json);
@override
@LogicalKeyboardSerializer()
final LogicalKeyboardKey? modifier;
@override
@LogicalKeyboardSerializer()
final LogicalKeyboardKey key;
@override
String toString() {
return 'KeyCombination(modifier: $modifier, key: $key)';
}
@override
Map<String, dynamic> toJson() {
return _$$KeyCombinationImplToJson(
this,
);
}
}
abstract class _KeyCombination extends KeyCombination {
factory _KeyCombination(
{@LogicalKeyboardSerializer() final LogicalKeyboardKey? modifier,
@LogicalKeyboardSerializer() required final LogicalKeyboardKey key}) =
_$KeyCombinationImpl;
_KeyCombination._() : super._();
factory _KeyCombination.fromJson(Map<String, dynamic> json) =
_$KeyCombinationImpl.fromJson;
@override
@LogicalKeyboardSerializer()
LogicalKeyboardKey? get modifier;
@override
@LogicalKeyboardSerializer()
LogicalKeyboardKey get key;
}

View file

@ -0,0 +1,34 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'key_combinations.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$KeyCombinationImpl _$$KeyCombinationImplFromJson(Map<String, dynamic> json) =>
_$KeyCombinationImpl(
modifier: _$JsonConverterFromJson<String, LogicalKeyboardKey>(
json['modifier'], const LogicalKeyboardSerializer().fromJson),
key: const LogicalKeyboardSerializer().fromJson(json['key'] as String),
);
Map<String, dynamic> _$$KeyCombinationImplToJson(
_$KeyCombinationImpl instance) =>
<String, dynamic>{
'modifier': _$JsonConverterToJson<String, LogicalKeyboardKey>(
instance.modifier, const LogicalKeyboardSerializer().toJson),
'key': const LogicalKeyboardSerializer().toJson(instance.key),
};
Value? _$JsonConverterFromJson<Json, Value>(
Object? json,
Value? Function(Json json) fromJson,
) =>
json == null ? null : fromJson(json as Json);
Json? _$JsonConverterToJson<Json, Value>(
Value? value,
Json? Function(Value value) toJson,
) =>
value == null ? null : toJson(value);

View file

@ -6,12 +6,49 @@ import 'package:flutter/widgets.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:fladder/models/items/media_segments_model.dart';
import 'package:fladder/models/settings/key_combinations.dart';
import 'package:fladder/util/bitrate_helper.dart';
import 'package:fladder/util/localization_helper.dart';
part 'video_player_settings.freezed.dart';
part 'video_player_settings.g.dart';
enum VideoHotKeys {
playPause,
seekForward,
seekBack,
mute,
volumeUp,
volumeDown,
nextVideo,
prevVideo,
nextChapter,
prevChapter,
fullScreen,
skipMediaSegment,
exit;
const VideoHotKeys();
String label(BuildContext context) {
return switch (this) {
VideoHotKeys.playPause => context.localized.playPause,
VideoHotKeys.seekForward => context.localized.seekForward,
VideoHotKeys.seekBack => context.localized.seekBack,
VideoHotKeys.mute => context.localized.mute,
VideoHotKeys.volumeUp => context.localized.volumeUp,
VideoHotKeys.volumeDown => context.localized.volumeDown,
VideoHotKeys.nextVideo => context.localized.nextVideo,
VideoHotKeys.prevVideo => context.localized.prevVideo,
VideoHotKeys.nextChapter => context.localized.nextChapter,
VideoHotKeys.prevChapter => context.localized.prevChapter,
VideoHotKeys.fullScreen => context.localized.fullScreen,
VideoHotKeys.skipMediaSegment => context.localized.skipMediaSegment,
VideoHotKeys.exit => context.localized.exit,
};
}
}
@Freezed(copyWith: true)
class VideoPlayerSettingsModel with _$VideoPlayerSettingsModel {
const VideoPlayerSettingsModel._();
@ -31,6 +68,7 @@ class VideoPlayerSettingsModel with _$VideoPlayerSettingsModel {
@Default(Bitrate.original) Bitrate maxInternetBitrate,
String? audioDevice,
@Default(defaultSegmentSkipValues) Map<MediaSegmentType, SegmentSkip> segmentSkipSettings,
@Default({}) Map<VideoHotKeys, KeyCombination?> hotKeys,
}) = _VideoPlayerSettingsModel;
double get volume => switch (defaultTargetPlatform) {
@ -42,6 +80,11 @@ class VideoPlayerSettingsModel with _$VideoPlayerSettingsModel {
PlayerOptions get wantedPlayer => playerOptions ?? PlayerOptions.platformDefaults;
Map<VideoHotKeys, KeyCombination> get currentShortcuts =>
_defaultVideoHotKeys.map((key, value) => MapEntry(key, hotKeys[key] ?? value));
Map<VideoHotKeys, KeyCombination> get defaultShortCuts => _defaultVideoHotKeys;
bool playerSame(VideoPlayerSettingsModel other) {
return other.hardwareAccel == hardwareAccel &&
other.useLibass == useLibass &&
@ -118,3 +161,22 @@ enum AutoNextType {
AutoNextType.static => context.localized.autoNextOffStaticDesc,
};
}
Map<VideoHotKeys, KeyCombination> get _defaultVideoHotKeys => {
for (var hotKey in VideoHotKeys.values)
hotKey: switch (hotKey) {
VideoHotKeys.playPause => KeyCombination(key: LogicalKeyboardKey.space),
VideoHotKeys.seekForward => KeyCombination(key: LogicalKeyboardKey.arrowRight),
VideoHotKeys.seekBack => KeyCombination(key: LogicalKeyboardKey.arrowLeft),
VideoHotKeys.mute => KeyCombination(key: LogicalKeyboardKey.keyM),
VideoHotKeys.volumeUp => KeyCombination(key: LogicalKeyboardKey.arrowUp),
VideoHotKeys.volumeDown => KeyCombination(key: LogicalKeyboardKey.arrowDown),
VideoHotKeys.prevVideo => KeyCombination(key: LogicalKeyboardKey.keyP, modifier: LogicalKeyboardKey.shift),
VideoHotKeys.nextVideo => KeyCombination(key: LogicalKeyboardKey.keyN, modifier: LogicalKeyboardKey.shift),
VideoHotKeys.nextChapter => KeyCombination(key: LogicalKeyboardKey.pageUp),
VideoHotKeys.prevChapter => KeyCombination(key: LogicalKeyboardKey.pageDown),
VideoHotKeys.fullScreen => KeyCombination(key: LogicalKeyboardKey.keyF),
VideoHotKeys.skipMediaSegment => KeyCombination(key: LogicalKeyboardKey.keyS),
VideoHotKeys.exit => KeyCombination(key: LogicalKeyboardKey.escape),
},
};

View file

@ -37,6 +37,8 @@ mixin _$VideoPlayerSettingsModel {
String? get audioDevice => throw _privateConstructorUsedError;
Map<MediaSegmentType, SegmentSkip> get segmentSkipSettings =>
throw _privateConstructorUsedError;
Map<VideoHotKeys, KeyCombination?> get hotKeys =>
throw _privateConstructorUsedError;
/// Serializes this VideoPlayerSettingsModel to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@ -68,7 +70,8 @@ abstract class $VideoPlayerSettingsModelCopyWith<$Res> {
Bitrate maxHomeBitrate,
Bitrate maxInternetBitrate,
String? audioDevice,
Map<MediaSegmentType, SegmentSkip> segmentSkipSettings});
Map<MediaSegmentType, SegmentSkip> segmentSkipSettings,
Map<VideoHotKeys, KeyCombination?> hotKeys});
}
/// @nodoc
@ -101,6 +104,7 @@ class _$VideoPlayerSettingsModelCopyWithImpl<$Res,
Object? maxInternetBitrate = null,
Object? audioDevice = freezed,
Object? segmentSkipSettings = null,
Object? hotKeys = null,
}) {
return _then(_value.copyWith(
screenBrightness: freezed == screenBrightness
@ -159,6 +163,10 @@ class _$VideoPlayerSettingsModelCopyWithImpl<$Res,
? _value.segmentSkipSettings
: segmentSkipSettings // ignore: cast_nullable_to_non_nullable
as Map<MediaSegmentType, SegmentSkip>,
hotKeys: null == hotKeys
? _value.hotKeys
: hotKeys // ignore: cast_nullable_to_non_nullable
as Map<VideoHotKeys, KeyCombination?>,
) as $Val);
}
}
@ -186,7 +194,8 @@ abstract class _$$VideoPlayerSettingsModelImplCopyWith<$Res>
Bitrate maxHomeBitrate,
Bitrate maxInternetBitrate,
String? audioDevice,
Map<MediaSegmentType, SegmentSkip> segmentSkipSettings});
Map<MediaSegmentType, SegmentSkip> segmentSkipSettings,
Map<VideoHotKeys, KeyCombination?> hotKeys});
}
/// @nodoc
@ -218,6 +227,7 @@ class __$$VideoPlayerSettingsModelImplCopyWithImpl<$Res>
Object? maxInternetBitrate = null,
Object? audioDevice = freezed,
Object? segmentSkipSettings = null,
Object? hotKeys = null,
}) {
return _then(_$VideoPlayerSettingsModelImpl(
screenBrightness: freezed == screenBrightness
@ -276,6 +286,10 @@ class __$$VideoPlayerSettingsModelImplCopyWithImpl<$Res>
? _value._segmentSkipSettings
: segmentSkipSettings // ignore: cast_nullable_to_non_nullable
as Map<MediaSegmentType, SegmentSkip>,
hotKeys: null == hotKeys
? _value._hotKeys
: hotKeys // ignore: cast_nullable_to_non_nullable
as Map<VideoHotKeys, KeyCombination?>,
));
}
}
@ -299,9 +313,11 @@ class _$VideoPlayerSettingsModelImpl extends _VideoPlayerSettingsModel
this.maxInternetBitrate = Bitrate.original,
this.audioDevice,
final Map<MediaSegmentType, SegmentSkip> segmentSkipSettings =
defaultSegmentSkipValues})
defaultSegmentSkipValues,
final Map<VideoHotKeys, KeyCombination?> hotKeys = const {}})
: _allowedOrientations = allowedOrientations,
_segmentSkipSettings = segmentSkipSettings,
_hotKeys = hotKeys,
super._();
factory _$VideoPlayerSettingsModelImpl.fromJson(Map<String, dynamic> json) =>
@ -361,9 +377,18 @@ class _$VideoPlayerSettingsModelImpl extends _VideoPlayerSettingsModel
return EqualUnmodifiableMapView(_segmentSkipSettings);
}
final Map<VideoHotKeys, KeyCombination?> _hotKeys;
@override
@JsonKey()
Map<VideoHotKeys, KeyCombination?> get hotKeys {
if (_hotKeys is EqualUnmodifiableMapView) return _hotKeys;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(_hotKeys);
}
@override
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
return 'VideoPlayerSettingsModel(screenBrightness: $screenBrightness, videoFit: $videoFit, fillScreen: $fillScreen, hardwareAccel: $hardwareAccel, useLibass: $useLibass, bufferSize: $bufferSize, playerOptions: $playerOptions, internalVolume: $internalVolume, allowedOrientations: $allowedOrientations, nextVideoType: $nextVideoType, maxHomeBitrate: $maxHomeBitrate, maxInternetBitrate: $maxInternetBitrate, audioDevice: $audioDevice, segmentSkipSettings: $segmentSkipSettings)';
return 'VideoPlayerSettingsModel(screenBrightness: $screenBrightness, videoFit: $videoFit, fillScreen: $fillScreen, hardwareAccel: $hardwareAccel, useLibass: $useLibass, bufferSize: $bufferSize, playerOptions: $playerOptions, internalVolume: $internalVolume, allowedOrientations: $allowedOrientations, nextVideoType: $nextVideoType, maxHomeBitrate: $maxHomeBitrate, maxInternetBitrate: $maxInternetBitrate, audioDevice: $audioDevice, segmentSkipSettings: $segmentSkipSettings, hotKeys: $hotKeys)';
}
@override
@ -384,7 +409,8 @@ class _$VideoPlayerSettingsModelImpl extends _VideoPlayerSettingsModel
..add(DiagnosticsProperty('maxHomeBitrate', maxHomeBitrate))
..add(DiagnosticsProperty('maxInternetBitrate', maxInternetBitrate))
..add(DiagnosticsProperty('audioDevice', audioDevice))
..add(DiagnosticsProperty('segmentSkipSettings', segmentSkipSettings));
..add(DiagnosticsProperty('segmentSkipSettings', segmentSkipSettings))
..add(DiagnosticsProperty('hotKeys', hotKeys));
}
/// Create a copy of VideoPlayerSettingsModel
@ -419,7 +445,8 @@ abstract class _VideoPlayerSettingsModel extends VideoPlayerSettingsModel {
final Bitrate maxHomeBitrate,
final Bitrate maxInternetBitrate,
final String? audioDevice,
final Map<MediaSegmentType, SegmentSkip> segmentSkipSettings}) =
final Map<MediaSegmentType, SegmentSkip> segmentSkipSettings,
final Map<VideoHotKeys, KeyCombination?> hotKeys}) =
_$VideoPlayerSettingsModelImpl;
_VideoPlayerSettingsModel._() : super._();
@ -454,6 +481,8 @@ abstract class _VideoPlayerSettingsModel extends VideoPlayerSettingsModel {
String? get audioDevice;
@override
Map<MediaSegmentType, SegmentSkip> get segmentSkipSettings;
@override
Map<VideoHotKeys, KeyCombination?> get hotKeys;
/// Create a copy of VideoPlayerSettingsModel
/// with the given fields replaced by the non-null parameter values.

View file

@ -38,6 +38,14 @@ _$VideoPlayerSettingsModelImpl _$$VideoPlayerSettingsModelImplFromJson(
$enumDecode(_$SegmentSkipEnumMap, e)),
) ??
defaultSegmentSkipValues,
hotKeys: (json['hotKeys'] as Map<String, dynamic>?)?.map(
(k, e) => MapEntry(
$enumDecode(_$VideoHotKeysEnumMap, k),
e == null
? null
: KeyCombination.fromJson(e as Map<String, dynamic>)),
) ??
const {},
);
Map<String, dynamic> _$$VideoPlayerSettingsModelImplToJson(
@ -60,6 +68,8 @@ Map<String, dynamic> _$$VideoPlayerSettingsModelImplToJson(
'audioDevice': instance.audioDevice,
'segmentSkipSettings': instance.segmentSkipSettings.map((k, e) =>
MapEntry(_$MediaSegmentTypeEnumMap[k]!, _$SegmentSkipEnumMap[e]!)),
'hotKeys': instance.hotKeys
.map((k, e) => MapEntry(_$VideoHotKeysEnumMap[k]!, e)),
};
const _$BoxFitEnumMap = {
@ -123,3 +133,19 @@ const _$MediaSegmentTypeEnumMap = {
MediaSegmentType.outro: 'outro',
MediaSegmentType.intro: 'intro',
};
const _$VideoHotKeysEnumMap = {
VideoHotKeys.playPause: 'playPause',
VideoHotKeys.seekForward: 'seekForward',
VideoHotKeys.seekBack: 'seekBack',
VideoHotKeys.mute: 'mute',
VideoHotKeys.volumeUp: 'volumeUp',
VideoHotKeys.volumeDown: 'volumeDown',
VideoHotKeys.nextVideo: 'nextVideo',
VideoHotKeys.prevVideo: 'prevVideo',
VideoHotKeys.nextChapter: 'nextChapter',
VideoHotKeys.prevChapter: 'prevChapter',
VideoHotKeys.fullScreen: 'fullScreen',
VideoHotKeys.skipMediaSegment: 'skipMediaSegment',
VideoHotKeys.exit: 'exit',
};