Fladder/lib/models/settings/video_player_settings.dart
PartyDonut 6357b9843c
chore:cleanup-packages breaking: remove isar (#474)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
2025-08-24 21:16:51 +02:00

193 lines
6.7 KiB
Dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
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)
abstract class VideoPlayerSettingsModel with _$VideoPlayerSettingsModel {
const VideoPlayerSettingsModel._();
factory VideoPlayerSettingsModel({
double? screenBrightness,
@Default(BoxFit.contain) BoxFit videoFit,
@Default(false) bool fillScreen,
@Default(true) bool hardwareAccel,
@Default(false) bool useLibass,
@Default(32) int bufferSize,
PlayerOptions? playerOptions,
@Default(100) double internalVolume,
Set<DeviceOrientation>? allowedOrientations,
@Default(AutoNextType.smart) AutoNextType nextVideoType,
@Default(Bitrate.original) Bitrate maxHomeBitrate,
@Default(Bitrate.original) Bitrate maxInternetBitrate,
String? audioDevice,
@Default(defaultSegmentSkipValues) Map<MediaSegmentType, SegmentSkip> segmentSkipSettings,
@Default({}) Map<VideoHotKeys, KeyCombination> hotKeys,
}) = _VideoPlayerSettingsModel;
double get volume => switch (defaultTargetPlatform) {
TargetPlatform.android || TargetPlatform.iOS => 100,
_ => internalVolume,
};
factory VideoPlayerSettingsModel.fromJson(Map<String, dynamic> json) => _$VideoPlayerSettingsModelFromJson(json);
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 &&
other.bufferSize == bufferSize &&
other.wantedPlayer == wantedPlayer;
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is VideoPlayerSettingsModel &&
other.screenBrightness == screenBrightness &&
other.videoFit == videoFit &&
other.fillScreen == fillScreen &&
other.hardwareAccel == hardwareAccel &&
other.useLibass == useLibass &&
other.bufferSize == bufferSize &&
other.internalVolume == internalVolume &&
other.playerOptions == playerOptions &&
other.audioDevice == audioDevice;
}
@override
int get hashCode {
return screenBrightness.hashCode ^
videoFit.hashCode ^
fillScreen.hashCode ^
hardwareAccel.hashCode ^
useLibass.hashCode ^
bufferSize.hashCode ^
internalVolume.hashCode ^
audioDevice.hashCode;
}
}
enum PlayerOptions {
libMDK,
libMPV;
const PlayerOptions();
static Iterable<PlayerOptions> get available => kIsWeb ? {PlayerOptions.libMPV} : PlayerOptions.values;
static PlayerOptions get platformDefaults {
if (kIsWeb) return PlayerOptions.libMPV;
return switch (defaultTargetPlatform) {
_ => PlayerOptions.libMPV,
};
}
String label(BuildContext context) => switch (this) {
PlayerOptions.libMDK => "MDK",
PlayerOptions.libMPV => "MPV",
};
}
enum AutoNextType {
off,
smart,
static;
const AutoNextType();
String label(BuildContext context) => switch (this) {
AutoNextType.off => context.localized.off,
AutoNextType.smart => context.localized.autoNextOffSmartTitle,
AutoNextType.static => context.localized.autoNextOffStaticTitle,
};
String desc(BuildContext context) => switch (this) {
AutoNextType.off => context.localized.off,
AutoNextType.smart => context.localized.autoNextOffSmartDesc,
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,
altKey: LogicalKeyboardKey.keyK,
),
VideoHotKeys.seekForward => KeyCombination(
key: LogicalKeyboardKey.arrowRight,
altKey: LogicalKeyboardKey.keyL,
),
VideoHotKeys.seekBack => KeyCombination(
key: LogicalKeyboardKey.arrowLeft,
altKey: LogicalKeyboardKey.keyJ,
),
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.shiftLeft),
VideoHotKeys.nextVideo =>
KeyCombination(key: LogicalKeyboardKey.keyN, modifier: LogicalKeyboardKey.shiftLeft),
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),
},
};