mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-11 00:10:29 -07:00
Init repo
This commit is contained in:
commit
764b6034e3
566 changed files with 212335 additions and 0 deletions
117
lib/models/settings/client_settings_model.dart
Normal file
117
lib/models/settings/client_settings_model.dart
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fladder/util/custom_color_themes.dart';
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'client_settings_model.freezed.dart';
|
||||
part 'client_settings_model.g.dart';
|
||||
|
||||
@freezed
|
||||
class ClientSettingsModel with _$ClientSettingsModel {
|
||||
factory ClientSettingsModel({
|
||||
String? syncPath,
|
||||
@Default(Vector2(x: 0, y: 0)) Vector2 position,
|
||||
@Default(Vector2(x: 1280, y: 720)) Vector2 size,
|
||||
@Default(Duration(seconds: 30)) Duration? timeOut,
|
||||
Duration? nextUpDateCutoff,
|
||||
@Default(ThemeMode.system) ThemeMode themeMode,
|
||||
ColorThemes? themeColor,
|
||||
@Default(false) bool amoledBlack,
|
||||
@Default(false) bool blurPlaceHolders,
|
||||
@Default(false) bool blurUpcomingEpisodes,
|
||||
@LocaleConvert() Locale? selectedLocale,
|
||||
@Default(true) bool enableMediaKeys,
|
||||
@Default(1.0) double posterSize,
|
||||
@Default(false) bool pinchPosterZoom,
|
||||
@Default(false) bool mouseDragSupport,
|
||||
int? libraryPageSize,
|
||||
}) = _ClientSettingsModel;
|
||||
|
||||
factory ClientSettingsModel.fromJson(Map<String, dynamic> json) => _$ClientSettingsModelFromJson(json);
|
||||
}
|
||||
|
||||
class LocaleConvert implements JsonConverter<Locale?, String?> {
|
||||
const LocaleConvert();
|
||||
|
||||
@override
|
||||
Locale? fromJson(String? json) {
|
||||
if (json == null) return null;
|
||||
final parts = json.split('_');
|
||||
if (parts.length == 1) {
|
||||
return Locale(parts[0]);
|
||||
} else if (parts.length == 2) {
|
||||
return Locale(parts[0], parts[1]);
|
||||
} else {
|
||||
log("Invalid Locale format");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String? toJson(Locale? object) {
|
||||
if (object == null) return null;
|
||||
if (object.countryCode == null || object.countryCode?.isEmpty == true) {
|
||||
return object.languageCode;
|
||||
}
|
||||
return '${object.languageCode}_${object.countryCode}';
|
||||
}
|
||||
}
|
||||
|
||||
class Vector2 {
|
||||
final double x;
|
||||
final double y;
|
||||
const Vector2({
|
||||
required this.x,
|
||||
required this.y,
|
||||
});
|
||||
|
||||
Vector2 copyWith({
|
||||
double? x,
|
||||
double? y,
|
||||
}) {
|
||||
return Vector2(
|
||||
x: x ?? this.x,
|
||||
y: y ?? this.y,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return <String, dynamic>{
|
||||
'x': x,
|
||||
'y': y,
|
||||
};
|
||||
}
|
||||
|
||||
factory Vector2.fromMap(Map<String, dynamic> map) {
|
||||
return Vector2(
|
||||
x: map['x'] as double,
|
||||
y: map['y'] as double,
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory Vector2.fromJson(String source) => Vector2.fromMap(json.decode(source) as Map<String, dynamic>);
|
||||
|
||||
factory Vector2.fromSize(Size size) => Vector2(x: size.width, y: size.height);
|
||||
|
||||
@override
|
||||
String toString() => 'Vector2(x: $x, y: $y)';
|
||||
|
||||
@override
|
||||
bool operator ==(covariant Vector2 other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other.x == x && other.y == y;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => x.hashCode ^ y.hashCode;
|
||||
|
||||
static fromPosition(Offset windowPosition) => Vector2(x: windowPosition.dx, y: windowPosition.dy);
|
||||
}
|
||||
526
lib/models/settings/client_settings_model.freezed.dart
Normal file
526
lib/models/settings/client_settings_model.freezed.dart
Normal file
|
|
@ -0,0 +1,526 @@
|
|||
// 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 'client_settings_model.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');
|
||||
|
||||
ClientSettingsModel _$ClientSettingsModelFromJson(Map<String, dynamic> json) {
|
||||
return _ClientSettingsModel.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ClientSettingsModel {
|
||||
String? get syncPath => throw _privateConstructorUsedError;
|
||||
Vector2 get position => throw _privateConstructorUsedError;
|
||||
Vector2 get size => throw _privateConstructorUsedError;
|
||||
Duration? get timeOut => throw _privateConstructorUsedError;
|
||||
Duration? get nextUpDateCutoff => throw _privateConstructorUsedError;
|
||||
ThemeMode get themeMode => throw _privateConstructorUsedError;
|
||||
ColorThemes? get themeColor => throw _privateConstructorUsedError;
|
||||
bool get amoledBlack => throw _privateConstructorUsedError;
|
||||
bool get blurPlaceHolders => throw _privateConstructorUsedError;
|
||||
bool get blurUpcomingEpisodes => throw _privateConstructorUsedError;
|
||||
@LocaleConvert()
|
||||
Locale? get selectedLocale => throw _privateConstructorUsedError;
|
||||
bool get enableMediaKeys => throw _privateConstructorUsedError;
|
||||
double get posterSize => throw _privateConstructorUsedError;
|
||||
bool get pinchPosterZoom => throw _privateConstructorUsedError;
|
||||
bool get mouseDragSupport => throw _privateConstructorUsedError;
|
||||
int? get libraryPageSize => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$ClientSettingsModelCopyWith<ClientSettingsModel> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ClientSettingsModelCopyWith<$Res> {
|
||||
factory $ClientSettingsModelCopyWith(
|
||||
ClientSettingsModel value, $Res Function(ClientSettingsModel) then) =
|
||||
_$ClientSettingsModelCopyWithImpl<$Res, ClientSettingsModel>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{String? syncPath,
|
||||
Vector2 position,
|
||||
Vector2 size,
|
||||
Duration? timeOut,
|
||||
Duration? nextUpDateCutoff,
|
||||
ThemeMode themeMode,
|
||||
ColorThemes? themeColor,
|
||||
bool amoledBlack,
|
||||
bool blurPlaceHolders,
|
||||
bool blurUpcomingEpisodes,
|
||||
@LocaleConvert() Locale? selectedLocale,
|
||||
bool enableMediaKeys,
|
||||
double posterSize,
|
||||
bool pinchPosterZoom,
|
||||
bool mouseDragSupport,
|
||||
int? libraryPageSize});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ClientSettingsModelCopyWithImpl<$Res, $Val extends ClientSettingsModel>
|
||||
implements $ClientSettingsModelCopyWith<$Res> {
|
||||
_$ClientSettingsModelCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? syncPath = freezed,
|
||||
Object? position = null,
|
||||
Object? size = null,
|
||||
Object? timeOut = freezed,
|
||||
Object? nextUpDateCutoff = freezed,
|
||||
Object? themeMode = null,
|
||||
Object? themeColor = freezed,
|
||||
Object? amoledBlack = null,
|
||||
Object? blurPlaceHolders = null,
|
||||
Object? blurUpcomingEpisodes = null,
|
||||
Object? selectedLocale = freezed,
|
||||
Object? enableMediaKeys = null,
|
||||
Object? posterSize = null,
|
||||
Object? pinchPosterZoom = null,
|
||||
Object? mouseDragSupport = null,
|
||||
Object? libraryPageSize = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
syncPath: freezed == syncPath
|
||||
? _value.syncPath
|
||||
: syncPath // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
position: null == position
|
||||
? _value.position
|
||||
: position // ignore: cast_nullable_to_non_nullable
|
||||
as Vector2,
|
||||
size: null == size
|
||||
? _value.size
|
||||
: size // ignore: cast_nullable_to_non_nullable
|
||||
as Vector2,
|
||||
timeOut: freezed == timeOut
|
||||
? _value.timeOut
|
||||
: timeOut // ignore: cast_nullable_to_non_nullable
|
||||
as Duration?,
|
||||
nextUpDateCutoff: freezed == nextUpDateCutoff
|
||||
? _value.nextUpDateCutoff
|
||||
: nextUpDateCutoff // ignore: cast_nullable_to_non_nullable
|
||||
as Duration?,
|
||||
themeMode: null == themeMode
|
||||
? _value.themeMode
|
||||
: themeMode // ignore: cast_nullable_to_non_nullable
|
||||
as ThemeMode,
|
||||
themeColor: freezed == themeColor
|
||||
? _value.themeColor
|
||||
: themeColor // ignore: cast_nullable_to_non_nullable
|
||||
as ColorThemes?,
|
||||
amoledBlack: null == amoledBlack
|
||||
? _value.amoledBlack
|
||||
: amoledBlack // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
blurPlaceHolders: null == blurPlaceHolders
|
||||
? _value.blurPlaceHolders
|
||||
: blurPlaceHolders // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
blurUpcomingEpisodes: null == blurUpcomingEpisodes
|
||||
? _value.blurUpcomingEpisodes
|
||||
: blurUpcomingEpisodes // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
selectedLocale: freezed == selectedLocale
|
||||
? _value.selectedLocale
|
||||
: selectedLocale // ignore: cast_nullable_to_non_nullable
|
||||
as Locale?,
|
||||
enableMediaKeys: null == enableMediaKeys
|
||||
? _value.enableMediaKeys
|
||||
: enableMediaKeys // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
posterSize: null == posterSize
|
||||
? _value.posterSize
|
||||
: posterSize // ignore: cast_nullable_to_non_nullable
|
||||
as double,
|
||||
pinchPosterZoom: null == pinchPosterZoom
|
||||
? _value.pinchPosterZoom
|
||||
: pinchPosterZoom // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
mouseDragSupport: null == mouseDragSupport
|
||||
? _value.mouseDragSupport
|
||||
: mouseDragSupport // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
libraryPageSize: freezed == libraryPageSize
|
||||
? _value.libraryPageSize
|
||||
: libraryPageSize // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ClientSettingsModelImplCopyWith<$Res>
|
||||
implements $ClientSettingsModelCopyWith<$Res> {
|
||||
factory _$$ClientSettingsModelImplCopyWith(_$ClientSettingsModelImpl value,
|
||||
$Res Function(_$ClientSettingsModelImpl) then) =
|
||||
__$$ClientSettingsModelImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{String? syncPath,
|
||||
Vector2 position,
|
||||
Vector2 size,
|
||||
Duration? timeOut,
|
||||
Duration? nextUpDateCutoff,
|
||||
ThemeMode themeMode,
|
||||
ColorThemes? themeColor,
|
||||
bool amoledBlack,
|
||||
bool blurPlaceHolders,
|
||||
bool blurUpcomingEpisodes,
|
||||
@LocaleConvert() Locale? selectedLocale,
|
||||
bool enableMediaKeys,
|
||||
double posterSize,
|
||||
bool pinchPosterZoom,
|
||||
bool mouseDragSupport,
|
||||
int? libraryPageSize});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ClientSettingsModelImplCopyWithImpl<$Res>
|
||||
extends _$ClientSettingsModelCopyWithImpl<$Res, _$ClientSettingsModelImpl>
|
||||
implements _$$ClientSettingsModelImplCopyWith<$Res> {
|
||||
__$$ClientSettingsModelImplCopyWithImpl(_$ClientSettingsModelImpl _value,
|
||||
$Res Function(_$ClientSettingsModelImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? syncPath = freezed,
|
||||
Object? position = null,
|
||||
Object? size = null,
|
||||
Object? timeOut = freezed,
|
||||
Object? nextUpDateCutoff = freezed,
|
||||
Object? themeMode = null,
|
||||
Object? themeColor = freezed,
|
||||
Object? amoledBlack = null,
|
||||
Object? blurPlaceHolders = null,
|
||||
Object? blurUpcomingEpisodes = null,
|
||||
Object? selectedLocale = freezed,
|
||||
Object? enableMediaKeys = null,
|
||||
Object? posterSize = null,
|
||||
Object? pinchPosterZoom = null,
|
||||
Object? mouseDragSupport = null,
|
||||
Object? libraryPageSize = freezed,
|
||||
}) {
|
||||
return _then(_$ClientSettingsModelImpl(
|
||||
syncPath: freezed == syncPath
|
||||
? _value.syncPath
|
||||
: syncPath // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
position: null == position
|
||||
? _value.position
|
||||
: position // ignore: cast_nullable_to_non_nullable
|
||||
as Vector2,
|
||||
size: null == size
|
||||
? _value.size
|
||||
: size // ignore: cast_nullable_to_non_nullable
|
||||
as Vector2,
|
||||
timeOut: freezed == timeOut
|
||||
? _value.timeOut
|
||||
: timeOut // ignore: cast_nullable_to_non_nullable
|
||||
as Duration?,
|
||||
nextUpDateCutoff: freezed == nextUpDateCutoff
|
||||
? _value.nextUpDateCutoff
|
||||
: nextUpDateCutoff // ignore: cast_nullable_to_non_nullable
|
||||
as Duration?,
|
||||
themeMode: null == themeMode
|
||||
? _value.themeMode
|
||||
: themeMode // ignore: cast_nullable_to_non_nullable
|
||||
as ThemeMode,
|
||||
themeColor: freezed == themeColor
|
||||
? _value.themeColor
|
||||
: themeColor // ignore: cast_nullable_to_non_nullable
|
||||
as ColorThemes?,
|
||||
amoledBlack: null == amoledBlack
|
||||
? _value.amoledBlack
|
||||
: amoledBlack // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
blurPlaceHolders: null == blurPlaceHolders
|
||||
? _value.blurPlaceHolders
|
||||
: blurPlaceHolders // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
blurUpcomingEpisodes: null == blurUpcomingEpisodes
|
||||
? _value.blurUpcomingEpisodes
|
||||
: blurUpcomingEpisodes // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
selectedLocale: freezed == selectedLocale
|
||||
? _value.selectedLocale
|
||||
: selectedLocale // ignore: cast_nullable_to_non_nullable
|
||||
as Locale?,
|
||||
enableMediaKeys: null == enableMediaKeys
|
||||
? _value.enableMediaKeys
|
||||
: enableMediaKeys // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
posterSize: null == posterSize
|
||||
? _value.posterSize
|
||||
: posterSize // ignore: cast_nullable_to_non_nullable
|
||||
as double,
|
||||
pinchPosterZoom: null == pinchPosterZoom
|
||||
? _value.pinchPosterZoom
|
||||
: pinchPosterZoom // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
mouseDragSupport: null == mouseDragSupport
|
||||
? _value.mouseDragSupport
|
||||
: mouseDragSupport // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
libraryPageSize: freezed == libraryPageSize
|
||||
? _value.libraryPageSize
|
||||
: libraryPageSize // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$ClientSettingsModelImpl
|
||||
with DiagnosticableTreeMixin
|
||||
implements _ClientSettingsModel {
|
||||
_$ClientSettingsModelImpl(
|
||||
{this.syncPath,
|
||||
this.position = const Vector2(x: 0, y: 0),
|
||||
this.size = const Vector2(x: 1280, y: 720),
|
||||
this.timeOut = const Duration(seconds: 30),
|
||||
this.nextUpDateCutoff,
|
||||
this.themeMode = ThemeMode.system,
|
||||
this.themeColor,
|
||||
this.amoledBlack = false,
|
||||
this.blurPlaceHolders = false,
|
||||
this.blurUpcomingEpisodes = false,
|
||||
@LocaleConvert() this.selectedLocale,
|
||||
this.enableMediaKeys = true,
|
||||
this.posterSize = 1.0,
|
||||
this.pinchPosterZoom = false,
|
||||
this.mouseDragSupport = false,
|
||||
this.libraryPageSize});
|
||||
|
||||
factory _$ClientSettingsModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$ClientSettingsModelImplFromJson(json);
|
||||
|
||||
@override
|
||||
final String? syncPath;
|
||||
@override
|
||||
@JsonKey()
|
||||
final Vector2 position;
|
||||
@override
|
||||
@JsonKey()
|
||||
final Vector2 size;
|
||||
@override
|
||||
@JsonKey()
|
||||
final Duration? timeOut;
|
||||
@override
|
||||
final Duration? nextUpDateCutoff;
|
||||
@override
|
||||
@JsonKey()
|
||||
final ThemeMode themeMode;
|
||||
@override
|
||||
final ColorThemes? themeColor;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool amoledBlack;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool blurPlaceHolders;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool blurUpcomingEpisodes;
|
||||
@override
|
||||
@LocaleConvert()
|
||||
final Locale? selectedLocale;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool enableMediaKeys;
|
||||
@override
|
||||
@JsonKey()
|
||||
final double posterSize;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool pinchPosterZoom;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool mouseDragSupport;
|
||||
@override
|
||||
final int? libraryPageSize;
|
||||
|
||||
@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, libraryPageSize: $libraryPageSize)';
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties
|
||||
..add(DiagnosticsProperty('type', 'ClientSettingsModel'))
|
||||
..add(DiagnosticsProperty('syncPath', syncPath))
|
||||
..add(DiagnosticsProperty('position', position))
|
||||
..add(DiagnosticsProperty('size', size))
|
||||
..add(DiagnosticsProperty('timeOut', timeOut))
|
||||
..add(DiagnosticsProperty('nextUpDateCutoff', nextUpDateCutoff))
|
||||
..add(DiagnosticsProperty('themeMode', themeMode))
|
||||
..add(DiagnosticsProperty('themeColor', themeColor))
|
||||
..add(DiagnosticsProperty('amoledBlack', amoledBlack))
|
||||
..add(DiagnosticsProperty('blurPlaceHolders', blurPlaceHolders))
|
||||
..add(DiagnosticsProperty('blurUpcomingEpisodes', blurUpcomingEpisodes))
|
||||
..add(DiagnosticsProperty('selectedLocale', selectedLocale))
|
||||
..add(DiagnosticsProperty('enableMediaKeys', enableMediaKeys))
|
||||
..add(DiagnosticsProperty('posterSize', posterSize))
|
||||
..add(DiagnosticsProperty('pinchPosterZoom', pinchPosterZoom))
|
||||
..add(DiagnosticsProperty('mouseDragSupport', mouseDragSupport))
|
||||
..add(DiagnosticsProperty('libraryPageSize', libraryPageSize));
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ClientSettingsModelImpl &&
|
||||
(identical(other.syncPath, syncPath) ||
|
||||
other.syncPath == syncPath) &&
|
||||
(identical(other.position, position) ||
|
||||
other.position == position) &&
|
||||
(identical(other.size, size) || other.size == size) &&
|
||||
(identical(other.timeOut, timeOut) || other.timeOut == timeOut) &&
|
||||
(identical(other.nextUpDateCutoff, nextUpDateCutoff) ||
|
||||
other.nextUpDateCutoff == nextUpDateCutoff) &&
|
||||
(identical(other.themeMode, themeMode) ||
|
||||
other.themeMode == themeMode) &&
|
||||
(identical(other.themeColor, themeColor) ||
|
||||
other.themeColor == themeColor) &&
|
||||
(identical(other.amoledBlack, amoledBlack) ||
|
||||
other.amoledBlack == amoledBlack) &&
|
||||
(identical(other.blurPlaceHolders, blurPlaceHolders) ||
|
||||
other.blurPlaceHolders == blurPlaceHolders) &&
|
||||
(identical(other.blurUpcomingEpisodes, blurUpcomingEpisodes) ||
|
||||
other.blurUpcomingEpisodes == blurUpcomingEpisodes) &&
|
||||
(identical(other.selectedLocale, selectedLocale) ||
|
||||
other.selectedLocale == selectedLocale) &&
|
||||
(identical(other.enableMediaKeys, enableMediaKeys) ||
|
||||
other.enableMediaKeys == enableMediaKeys) &&
|
||||
(identical(other.posterSize, posterSize) ||
|
||||
other.posterSize == posterSize) &&
|
||||
(identical(other.pinchPosterZoom, pinchPosterZoom) ||
|
||||
other.pinchPosterZoom == pinchPosterZoom) &&
|
||||
(identical(other.mouseDragSupport, mouseDragSupport) ||
|
||||
other.mouseDragSupport == mouseDragSupport) &&
|
||||
(identical(other.libraryPageSize, libraryPageSize) ||
|
||||
other.libraryPageSize == libraryPageSize));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
syncPath,
|
||||
position,
|
||||
size,
|
||||
timeOut,
|
||||
nextUpDateCutoff,
|
||||
themeMode,
|
||||
themeColor,
|
||||
amoledBlack,
|
||||
blurPlaceHolders,
|
||||
blurUpcomingEpisodes,
|
||||
selectedLocale,
|
||||
enableMediaKeys,
|
||||
posterSize,
|
||||
pinchPosterZoom,
|
||||
mouseDragSupport,
|
||||
libraryPageSize);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ClientSettingsModelImplCopyWith<_$ClientSettingsModelImpl> get copyWith =>
|
||||
__$$ClientSettingsModelImplCopyWithImpl<_$ClientSettingsModelImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$ClientSettingsModelImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _ClientSettingsModel implements 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 int? libraryPageSize}) = _$ClientSettingsModelImpl;
|
||||
|
||||
factory _ClientSettingsModel.fromJson(Map<String, dynamic> json) =
|
||||
_$ClientSettingsModelImpl.fromJson;
|
||||
|
||||
@override
|
||||
String? get syncPath;
|
||||
@override
|
||||
Vector2 get position;
|
||||
@override
|
||||
Vector2 get size;
|
||||
@override
|
||||
Duration? get timeOut;
|
||||
@override
|
||||
Duration? get nextUpDateCutoff;
|
||||
@override
|
||||
ThemeMode get themeMode;
|
||||
@override
|
||||
ColorThemes? get themeColor;
|
||||
@override
|
||||
bool get amoledBlack;
|
||||
@override
|
||||
bool get blurPlaceHolders;
|
||||
@override
|
||||
bool get blurUpcomingEpisodes;
|
||||
@override
|
||||
@LocaleConvert()
|
||||
Locale? get selectedLocale;
|
||||
@override
|
||||
bool get enableMediaKeys;
|
||||
@override
|
||||
double get posterSize;
|
||||
@override
|
||||
bool get pinchPosterZoom;
|
||||
@override
|
||||
bool get mouseDragSupport;
|
||||
@override
|
||||
int? get libraryPageSize;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$ClientSettingsModelImplCopyWith<_$ClientSettingsModelImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
83
lib/models/settings/client_settings_model.g.dart
Normal file
83
lib/models/settings/client_settings_model.g.dart
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'client_settings_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$ClientSettingsModelImpl _$$ClientSettingsModelImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$ClientSettingsModelImpl(
|
||||
syncPath: json['syncPath'] as String?,
|
||||
position: json['position'] == null
|
||||
? const Vector2(x: 0, y: 0)
|
||||
: Vector2.fromJson(json['position'] as String),
|
||||
size: json['size'] == null
|
||||
? const Vector2(x: 1280, y: 720)
|
||||
: Vector2.fromJson(json['size'] as String),
|
||||
timeOut: json['timeOut'] == null
|
||||
? const Duration(seconds: 30)
|
||||
: Duration(microseconds: (json['timeOut'] as num).toInt()),
|
||||
nextUpDateCutoff: json['nextUpDateCutoff'] == null
|
||||
? null
|
||||
: Duration(microseconds: (json['nextUpDateCutoff'] as num).toInt()),
|
||||
themeMode: $enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode']) ??
|
||||
ThemeMode.system,
|
||||
themeColor: $enumDecodeNullable(_$ColorThemesEnumMap, json['themeColor']),
|
||||
amoledBlack: json['amoledBlack'] as bool? ?? false,
|
||||
blurPlaceHolders: json['blurPlaceHolders'] as bool? ?? false,
|
||||
blurUpcomingEpisodes: json['blurUpcomingEpisodes'] as bool? ?? false,
|
||||
selectedLocale:
|
||||
const LocaleConvert().fromJson(json['selectedLocale'] as String?),
|
||||
enableMediaKeys: json['enableMediaKeys'] as bool? ?? true,
|
||||
posterSize: (json['posterSize'] as num?)?.toDouble() ?? 1.0,
|
||||
pinchPosterZoom: json['pinchPosterZoom'] as bool? ?? false,
|
||||
mouseDragSupport: json['mouseDragSupport'] as bool? ?? false,
|
||||
libraryPageSize: (json['libraryPageSize'] as num?)?.toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ClientSettingsModelImplToJson(
|
||||
_$ClientSettingsModelImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'syncPath': instance.syncPath,
|
||||
'position': instance.position,
|
||||
'size': instance.size,
|
||||
'timeOut': instance.timeOut?.inMicroseconds,
|
||||
'nextUpDateCutoff': instance.nextUpDateCutoff?.inMicroseconds,
|
||||
'themeMode': _$ThemeModeEnumMap[instance.themeMode]!,
|
||||
'themeColor': _$ColorThemesEnumMap[instance.themeColor],
|
||||
'amoledBlack': instance.amoledBlack,
|
||||
'blurPlaceHolders': instance.blurPlaceHolders,
|
||||
'blurUpcomingEpisodes': instance.blurUpcomingEpisodes,
|
||||
'selectedLocale': const LocaleConvert().toJson(instance.selectedLocale),
|
||||
'enableMediaKeys': instance.enableMediaKeys,
|
||||
'posterSize': instance.posterSize,
|
||||
'pinchPosterZoom': instance.pinchPosterZoom,
|
||||
'mouseDragSupport': instance.mouseDragSupport,
|
||||
'libraryPageSize': instance.libraryPageSize,
|
||||
};
|
||||
|
||||
const _$ThemeModeEnumMap = {
|
||||
ThemeMode.system: 'system',
|
||||
ThemeMode.light: 'light',
|
||||
ThemeMode.dark: 'dark',
|
||||
};
|
||||
|
||||
const _$ColorThemesEnumMap = {
|
||||
ColorThemes.fladder: 'fladder',
|
||||
ColorThemes.deepOrange: 'deepOrange',
|
||||
ColorThemes.amber: 'amber',
|
||||
ColorThemes.green: 'green',
|
||||
ColorThemes.lightGreen: 'lightGreen',
|
||||
ColorThemes.lime: 'lime',
|
||||
ColorThemes.cyan: 'cyan',
|
||||
ColorThemes.blue: 'blue',
|
||||
ColorThemes.lightBlue: 'lightBlue',
|
||||
ColorThemes.indigo: 'indigo',
|
||||
ColorThemes.deepBlue: 'deepBlue',
|
||||
ColorThemes.brown: 'brown',
|
||||
ColorThemes.purple: 'purple',
|
||||
ColorThemes.deepPurple: 'deepPurple',
|
||||
ColorThemes.blueGrey: 'blueGrey',
|
||||
};
|
||||
108
lib/models/settings/home_settings_model.dart
Normal file
108
lib/models/settings/home_settings_model.dart
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
enum HomeCarouselSettings {
|
||||
off,
|
||||
nextUp,
|
||||
cont,
|
||||
combined,
|
||||
;
|
||||
|
||||
const HomeCarouselSettings();
|
||||
|
||||
String label(BuildContext context) => switch (this) {
|
||||
HomeCarouselSettings.off => context.localized.hide,
|
||||
HomeCarouselSettings.nextUp => context.localized.nextUp,
|
||||
HomeCarouselSettings.cont => context.localized.settingsContinue,
|
||||
HomeCarouselSettings.combined => context.localized.combined,
|
||||
};
|
||||
|
||||
String toMap() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
static HomeCarouselSettings fromMap(String value) {
|
||||
return HomeCarouselSettings.values.firstWhereOrNull((element) => element.name == value) ??
|
||||
HomeCarouselSettings.combined;
|
||||
}
|
||||
}
|
||||
|
||||
enum HomeNextUp {
|
||||
off,
|
||||
nextUp,
|
||||
cont,
|
||||
combined,
|
||||
separate,
|
||||
;
|
||||
|
||||
const HomeNextUp();
|
||||
|
||||
String label(BuildContext context) => switch (this) {
|
||||
HomeNextUp.off => context.localized.hide,
|
||||
HomeNextUp.nextUp => context.localized.nextUp,
|
||||
HomeNextUp.cont => context.localized.settingsContinue,
|
||||
HomeNextUp.combined => context.localized.combined,
|
||||
HomeNextUp.separate => context.localized.separate,
|
||||
};
|
||||
|
||||
String toMap() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
static HomeNextUp fromMap(String value) {
|
||||
return HomeNextUp.values.firstWhereOrNull((element) => element.name == value) ?? HomeNextUp.separate;
|
||||
}
|
||||
}
|
||||
|
||||
class HomeSettingsModel {
|
||||
final HomeCarouselSettings carouselSettings;
|
||||
final HomeNextUp nextUp;
|
||||
HomeSettingsModel({
|
||||
this.carouselSettings = HomeCarouselSettings.combined,
|
||||
this.nextUp = HomeNextUp.separate,
|
||||
});
|
||||
|
||||
HomeSettingsModel copyWith({
|
||||
HomeCarouselSettings? carouselSettings,
|
||||
HomeNextUp? nextUp,
|
||||
}) {
|
||||
return HomeSettingsModel(
|
||||
carouselSettings: carouselSettings ?? this.carouselSettings,
|
||||
nextUp: nextUp ?? this.nextUp,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'carouselSettings': carouselSettings.toMap(),
|
||||
'nextUp': nextUp.toMap(),
|
||||
};
|
||||
}
|
||||
|
||||
factory HomeSettingsModel.fromMap(Map<String, dynamic> map) {
|
||||
return HomeSettingsModel(
|
||||
carouselSettings: HomeCarouselSettings.fromMap(map['carouselSettings']),
|
||||
nextUp: HomeNextUp.fromMap(map['nextUp']),
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory HomeSettingsModel.fromJson(String source) => HomeSettingsModel.fromMap(json.decode(source));
|
||||
|
||||
@override
|
||||
String toString() => 'HomeSettingsModel(carouselSettings: $carouselSettings, nextUp: $nextUp)';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is HomeSettingsModel && other.carouselSettings == carouselSettings && other.nextUp == nextUp;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => carouselSettings.hashCode ^ nextUp.hashCode;
|
||||
}
|
||||
254
lib/models/settings/subtitle_settings_model.dart
Normal file
254
lib/models/settings/subtitle_settings_model.dart
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'dart:convert';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:fladder/providers/settings/subtitle_settings_provider.dart';
|
||||
import 'package:fladder/providers/settings/video_player_settings_provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
class SubtitleSettingsModel {
|
||||
final double fontSize;
|
||||
final FontWeight fontWeight;
|
||||
final double verticalOffset;
|
||||
final Color color;
|
||||
final Color outlineColor;
|
||||
final double outlineSize;
|
||||
final Color backGroundColor;
|
||||
final double shadow;
|
||||
const SubtitleSettingsModel({
|
||||
this.fontSize = 60,
|
||||
this.fontWeight = FontWeight.normal,
|
||||
this.verticalOffset = 0.10,
|
||||
this.color = Colors.white,
|
||||
this.outlineColor = const Color.fromRGBO(0, 0, 0, 0.85),
|
||||
this.outlineSize = 4,
|
||||
this.backGroundColor = const Color.fromARGB(0, 0, 0, 0),
|
||||
this.shadow = 0.5,
|
||||
});
|
||||
|
||||
SubtitleSettingsModel copyWith({
|
||||
double? fontSize,
|
||||
FontWeight? fontWeight,
|
||||
double? verticalOffset,
|
||||
Color? color,
|
||||
Color? outlineColor,
|
||||
double? outlineSize,
|
||||
Color? backGroundColor,
|
||||
double? shadow,
|
||||
}) {
|
||||
return SubtitleSettingsModel(
|
||||
fontSize: fontSize ?? this.fontSize,
|
||||
fontWeight: fontWeight ?? this.fontWeight,
|
||||
verticalOffset: verticalOffset ?? this.verticalOffset,
|
||||
color: color ?? this.color,
|
||||
outlineColor: outlineColor ?? this.outlineColor,
|
||||
outlineSize: outlineSize ?? this.outlineSize,
|
||||
backGroundColor: backGroundColor ?? this.backGroundColor,
|
||||
shadow: shadow ?? this.shadow,
|
||||
);
|
||||
}
|
||||
|
||||
TextStyle get backGroundStyle {
|
||||
return style.copyWith(
|
||||
shadows: (shadow > 0.01)
|
||||
? [
|
||||
Shadow(
|
||||
blurRadius: 16,
|
||||
color: Colors.black.withOpacity(shadow),
|
||||
),
|
||||
Shadow(
|
||||
blurRadius: 8,
|
||||
color: Colors.black.withOpacity(shadow),
|
||||
),
|
||||
]
|
||||
: null,
|
||||
foreground: Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = outlineSize * (fontSize / 30)
|
||||
..color = outlineColor
|
||||
..strokeCap = StrokeCap.round
|
||||
..strokeJoin = StrokeJoin.round,
|
||||
);
|
||||
}
|
||||
|
||||
TextStyle get style {
|
||||
return TextStyle(
|
||||
height: 1.4,
|
||||
fontSize: fontSize,
|
||||
fontWeight: fontWeight,
|
||||
fontFamily: GoogleFonts.openSans().fontFamily,
|
||||
letterSpacing: 0.0,
|
||||
wordSpacing: 0.0,
|
||||
color: color,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return <String, dynamic>{
|
||||
'fontSize': fontSize,
|
||||
'fontWeight': fontWeight.value,
|
||||
'verticalOffset': verticalOffset,
|
||||
'color': color.value,
|
||||
'outlineColor': outlineColor.value,
|
||||
'outlineSize': outlineSize,
|
||||
'backGroundColor': backGroundColor.value,
|
||||
'shadow': shadow,
|
||||
};
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory SubtitleSettingsModel.fromJson(String source) => SubtitleSettingsModel.fromMap(json.decode(source));
|
||||
|
||||
factory SubtitleSettingsModel.fromMap(Map<String, dynamic> map) {
|
||||
return const SubtitleSettingsModel().copyWith(
|
||||
fontSize: map['fontSize'] as double?,
|
||||
fontWeight: FontWeight.values.firstWhereOrNull((element) => element.index == map['fontWeight'] as int?),
|
||||
verticalOffset: map['verticalOffset'] as double?,
|
||||
color: map['color'] != null ? Color(map['color'] as int) : null,
|
||||
outlineColor: map['outlineColor'] != null ? Color(map['outlineColor'] as int) : null,
|
||||
outlineSize: map['outlineSize'] as double?,
|
||||
backGroundColor: map['backGroundColor'] != null ? Color(map['backGroundColor'] as int) : null,
|
||||
shadow: map['shadow'] as double?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SubtitleSettingsModel(fontSize: $fontSize, fontWeight: $fontWeight, verticalOffset: $verticalOffset, color: $color, outlineColor: $outlineColor, outlineSize: $outlineSize, backGroundColor: $backGroundColor, shadow: $shadow)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(covariant SubtitleSettingsModel other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other.fontSize == fontSize &&
|
||||
other.fontWeight == fontWeight &&
|
||||
other.verticalOffset == verticalOffset &&
|
||||
other.color == color &&
|
||||
other.outlineColor == outlineColor &&
|
||||
other.outlineSize == outlineSize &&
|
||||
other.backGroundColor == backGroundColor &&
|
||||
other.shadow == shadow;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return fontSize.hashCode ^
|
||||
fontWeight.hashCode ^
|
||||
verticalOffset.hashCode ^
|
||||
color.hashCode ^
|
||||
outlineColor.hashCode ^
|
||||
outlineSize.hashCode ^
|
||||
backGroundColor.hashCode ^
|
||||
shadow.hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
class SubtitleText extends ConsumerWidget {
|
||||
final SubtitleSettingsModel subModel;
|
||||
final EdgeInsets padding;
|
||||
final String text;
|
||||
final double offset;
|
||||
const SubtitleText({
|
||||
required this.subModel,
|
||||
required this.padding,
|
||||
required this.offset,
|
||||
required this.text,
|
||||
super.key,
|
||||
});
|
||||
|
||||
// The reference width for calculating the visible text scale factor.
|
||||
static const kTextScaleFactorReferenceWidth = 1920.0;
|
||||
// The reference height for calculating the visible text scale factor.
|
||||
static const kTextScaleFactorReferenceHeight = 1080.0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final fillScreen = ref.watch(videoPlayerSettingsProvider.select((value) => value.fillScreen));
|
||||
return Padding(
|
||||
padding: (fillScreen ? EdgeInsets.zero : EdgeInsets.only(left: padding.left, right: padding.right))
|
||||
.add(const EdgeInsets.all(16)),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final textScale = MediaQuery.textScalerOf(context)
|
||||
.scale((ref.read(subtitleSettingsProvider.select((value) => value.fontSize)) *
|
||||
math.sqrt(
|
||||
((constraints.maxWidth * constraints.maxHeight) /
|
||||
(kTextScaleFactorReferenceWidth * kTextScaleFactorReferenceHeight))
|
||||
.clamp(0.0, 1.0),
|
||||
)));
|
||||
|
||||
// Function to calculate the height of the text
|
||||
double getTextHeight(BuildContext context, String text, TextStyle style) {
|
||||
final TextPainter textPainter = TextPainter(
|
||||
text: TextSpan(text: text, style: style),
|
||||
textDirection: TextDirection.ltr,
|
||||
textScaler: MediaQuery.textScalerOf(context),
|
||||
)..layout(minWidth: 0, maxWidth: double.infinity);
|
||||
|
||||
return textPainter.height;
|
||||
}
|
||||
|
||||
// Calculate the available height for the text alignment
|
||||
double availableHeight = constraints.maxHeight;
|
||||
|
||||
// Calculate the desired position based on the percentage
|
||||
double desiredPosition = availableHeight * offset;
|
||||
|
||||
// Get the height of the Text widget with the current font style
|
||||
double textHeight = getTextHeight(context, text, subModel.style);
|
||||
|
||||
// Calculate the position to keep the text within visible bounds
|
||||
double position = desiredPosition - textHeight / 2;
|
||||
|
||||
// Ensure the text doesn't go off-screen
|
||||
position = position.clamp(0, availableHeight - textHeight);
|
||||
|
||||
return IgnorePointer(
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomCenter,
|
||||
children: [
|
||||
Positioned(
|
||||
bottom: position,
|
||||
child: Container(
|
||||
constraints: BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraints.maxHeight),
|
||||
decoration: BoxDecoration(
|
||||
color: subModel.backGroundColor,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
text,
|
||||
style: subModel.backGroundStyle.copyWith(fontSize: textScale),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: position,
|
||||
child: Container(
|
||||
constraints: BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraints.maxHeight),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
text,
|
||||
style: subModel.style.copyWith(fontSize: textScale),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
113
lib/models/settings/video_player_settings.dart
Normal file
113
lib/models/settings/video_player_settings.dart
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class VideoPlayerSettingsModel {
|
||||
final double? screenBrightness;
|
||||
final BoxFit videoFit;
|
||||
final bool fillScreen;
|
||||
final bool hardwareAccel;
|
||||
final bool useLibass;
|
||||
final double internalVolume;
|
||||
final String? audioDevice;
|
||||
const VideoPlayerSettingsModel({
|
||||
this.screenBrightness,
|
||||
this.videoFit = BoxFit.contain,
|
||||
this.fillScreen = false,
|
||||
this.hardwareAccel = true,
|
||||
this.useLibass = false,
|
||||
this.internalVolume = 100,
|
||||
this.audioDevice,
|
||||
});
|
||||
|
||||
double get volume => switch (defaultTargetPlatform) {
|
||||
TargetPlatform.android || TargetPlatform.iOS => 100,
|
||||
_ => internalVolume,
|
||||
};
|
||||
|
||||
VideoPlayerSettingsModel copyWith({
|
||||
ValueGetter<double?>? screenBrightness,
|
||||
BoxFit? videoFit,
|
||||
bool? fillScreen,
|
||||
bool? hardwareAccel,
|
||||
bool? useLibass,
|
||||
double? internalVolume,
|
||||
ValueGetter<String?>? audioDevice,
|
||||
}) {
|
||||
return VideoPlayerSettingsModel(
|
||||
screenBrightness: screenBrightness != null ? screenBrightness() : this.screenBrightness,
|
||||
videoFit: videoFit ?? this.videoFit,
|
||||
fillScreen: fillScreen ?? this.fillScreen,
|
||||
hardwareAccel: hardwareAccel ?? this.hardwareAccel,
|
||||
useLibass: useLibass ?? this.useLibass,
|
||||
internalVolume: internalVolume ?? this.internalVolume,
|
||||
audioDevice: audioDevice != null ? audioDevice() : this.audioDevice,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'screenBrightness': screenBrightness,
|
||||
'videoFit': videoFit.name,
|
||||
'fillScreen': fillScreen,
|
||||
'hardwareAccel': hardwareAccel,
|
||||
'useLibass': useLibass,
|
||||
'internalVolume': internalVolume,
|
||||
'audioDevice': audioDevice,
|
||||
};
|
||||
}
|
||||
|
||||
factory VideoPlayerSettingsModel.fromMap(Map<String, dynamic> map) {
|
||||
return VideoPlayerSettingsModel(
|
||||
screenBrightness: map['screenBrightness']?.toDouble(),
|
||||
videoFit: BoxFit.values.firstWhereOrNull((element) => element.name == map['videoFit']) ?? BoxFit.contain,
|
||||
fillScreen: map['fillScreen'] ?? false,
|
||||
hardwareAccel: map['hardwareAccel'] ?? false,
|
||||
useLibass: map['useLibass'] ?? false,
|
||||
internalVolume: map['internalVolume']?.toDouble() ?? 0.0,
|
||||
audioDevice: map['audioDevice'],
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory VideoPlayerSettingsModel.fromJson(String source) => VideoPlayerSettingsModel.fromMap(json.decode(source));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'VideoPlayerSettingsModel(screenBrightness: $screenBrightness, videoFit: $videoFit, fillScreen: $fillScreen, hardwareAccel: $hardwareAccel, useLibass: $useLibass, internalVolume: $internalVolume, audioDevice: $audioDevice)';
|
||||
}
|
||||
|
||||
bool playerSame(VideoPlayerSettingsModel other) {
|
||||
return other.hardwareAccel == hardwareAccel && other.useLibass == useLibass;
|
||||
}
|
||||
|
||||
@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.internalVolume == internalVolume &&
|
||||
other.audioDevice == audioDevice;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return screenBrightness.hashCode ^
|
||||
videoFit.hashCode ^
|
||||
fillScreen.hashCode ^
|
||||
hardwareAccel.hashCode ^
|
||||
useLibass.hashCode ^
|
||||
internalVolume.hashCode ^
|
||||
audioDevice.hashCode;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue