feature: Add support for mediaSegments (#138)

Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
PartyDonut 2024-11-09 19:40:12 +01:00 committed by GitHub
parent 36758bd508
commit 5c560e54b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 6823 additions and 8312 deletions

View file

@ -4,7 +4,8 @@
"jellyfin", "jellyfin",
"Jellyfin", "Jellyfin",
"LTRB", "LTRB",
"LTWH" "LTWH",
"outro"
], ],
"dart.flutterSdkPath": ".fvm/versions/3.24.3", "dart.flutterSdkPath": ".fvm/versions/3.24.3",
"search.exclude": { "search.exclude": {

View file

@ -1,20 +1,6 @@
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
enum AnalysisMode {
@JsonValue(null)
swaggerGeneratedUnknown(null),
@JsonValue('Introduction')
introduction('Introduction'),
@JsonValue('Credits')
credits('Credits');
final String? value;
const AnalysisMode(this.value);
}
enum AudioSpatialFormat { enum AudioSpatialFormat {
@JsonValue(null) @JsonValue(null)
swaggerGeneratedUnknown(null), swaggerGeneratedUnknown(null),
@ -313,6 +299,20 @@ enum DayPattern {
const DayPattern(this.value); const DayPattern(this.value);
} }
enum DeinterlaceMethod {
@JsonValue(null)
swaggerGeneratedUnknown(null),
@JsonValue('yadif')
yadif('yadif'),
@JsonValue('bwdif')
bwdif('bwdif');
final String? value;
const DeinterlaceMethod(this.value);
}
enum DlnaProfileType { enum DlnaProfileType {
@JsonValue(null) @JsonValue(null)
swaggerGeneratedUnknown(null), swaggerGeneratedUnknown(null),
@ -342,7 +342,11 @@ enum DownMixStereoAlgorithms {
@JsonValue('Dave750') @JsonValue('Dave750')
dave750('Dave750'), dave750('Dave750'),
@JsonValue('NightmodeDialogue') @JsonValue('NightmodeDialogue')
nightmodedialogue('NightmodeDialogue'); nightmodedialogue('NightmodeDialogue'),
@JsonValue('Rfc7845')
rfc7845('Rfc7845'),
@JsonValue('Ac4')
ac4('Ac4');
final String? value; final String? value;
@ -397,6 +401,38 @@ enum EmbeddedSubtitleOptions {
const EmbeddedSubtitleOptions(this.value); const EmbeddedSubtitleOptions(this.value);
} }
enum EncoderPreset {
@JsonValue(null)
swaggerGeneratedUnknown(null),
@JsonValue('auto')
auto('auto'),
@JsonValue('placebo')
placebo('placebo'),
@JsonValue('veryslow')
veryslow('veryslow'),
@JsonValue('slower')
slower('slower'),
@JsonValue('slow')
slow('slow'),
@JsonValue('medium')
medium('medium'),
@JsonValue('fast')
fast('fast'),
@JsonValue('faster')
faster('faster'),
@JsonValue('veryfast')
veryfast('veryfast'),
@JsonValue('superfast')
superfast('superfast'),
@JsonValue('ultrafast')
ultrafast('ultrafast');
final String? value;
const EncoderPreset(this.value);
}
enum EncodingContext { enum EncodingContext {
@JsonValue(null) @JsonValue(null)
swaggerGeneratedUnknown(null), swaggerGeneratedUnknown(null),
@ -705,28 +741,30 @@ enum GroupUpdateType {
const GroupUpdateType(this.value); const GroupUpdateType(this.value);
} }
enum HardwareEncodingType { enum HardwareAccelerationType {
@JsonValue(null) @JsonValue(null)
swaggerGeneratedUnknown(null), swaggerGeneratedUnknown(null),
@JsonValue('AMF') @JsonValue('none')
amf('AMF'), none('none'),
@JsonValue('QSV') @JsonValue('amf')
qsv('QSV'), amf('amf'),
@JsonValue('NVENC') @JsonValue('qsv')
nvenc('NVENC'), qsv('qsv'),
@JsonValue('V4L2M2M') @JsonValue('nvenc')
v4l2m2m('V4L2M2M'), nvenc('nvenc'),
@JsonValue('VAAPI') @JsonValue('v4l2m2m')
vaapi('VAAPI'), v4l2m2m('v4l2m2m'),
@JsonValue('VideoToolBox') @JsonValue('vaapi')
videotoolbox('VideoToolBox'), vaapi('vaapi'),
@JsonValue('RKMPP') @JsonValue('videotoolbox')
rkmpp('RKMPP'); videotoolbox('videotoolbox'),
@JsonValue('rkmpp')
rkmpp('rkmpp');
final String? value; final String? value;
const HardwareEncodingType(this.value); const HardwareAccelerationType(this.value);
} }
enum ImageFormat { enum ImageFormat {
@ -1199,6 +1237,28 @@ enum MediaProtocol {
const MediaProtocol(this.value); const MediaProtocol(this.value);
} }
enum MediaSegmentType {
@JsonValue(null)
swaggerGeneratedUnknown(null),
@JsonValue('Unknown')
unknown('Unknown'),
@JsonValue('Commercial')
commercial('Commercial'),
@JsonValue('Preview')
preview('Preview'),
@JsonValue('Recap')
recap('Recap'),
@JsonValue('Outro')
outro('Outro'),
@JsonValue('Intro')
intro('Intro');
final String? value;
const MediaSegmentType(this.value);
}
enum MediaSourceType { enum MediaSourceType {
@JsonValue(null) @JsonValue(null)
swaggerGeneratedUnknown(null), swaggerGeneratedUnknown(null),
@ -2011,6 +2071,68 @@ enum TaskState {
const TaskState(this.value); const TaskState(this.value);
} }
enum TonemappingAlgorithm {
@JsonValue(null)
swaggerGeneratedUnknown(null),
@JsonValue('none')
none('none'),
@JsonValue('clip')
clip('clip'),
@JsonValue('linear')
linear('linear'),
@JsonValue('gamma')
gamma('gamma'),
@JsonValue('reinhard')
reinhard('reinhard'),
@JsonValue('hable')
hable('hable'),
@JsonValue('mobius')
mobius('mobius'),
@JsonValue('bt2390')
bt2390('bt2390');
final String? value;
const TonemappingAlgorithm(this.value);
}
enum TonemappingMode {
@JsonValue(null)
swaggerGeneratedUnknown(null),
@JsonValue('auto')
auto('auto'),
@JsonValue('max')
max('max'),
@JsonValue('rgb')
rgb('rgb'),
@JsonValue('lum')
lum('lum'),
@JsonValue('itp')
itp('itp');
final String? value;
const TonemappingMode(this.value);
}
enum TonemappingRange {
@JsonValue(null)
swaggerGeneratedUnknown(null),
@JsonValue('auto')
auto('auto'),
@JsonValue('tv')
tv('tv'),
@JsonValue('pc')
pc('pc');
final String? value;
const TonemappingRange(this.value);
}
enum TranscodeReason { enum TranscodeReason {
@JsonValue(null) @JsonValue(null)
swaggerGeneratedUnknown(null), swaggerGeneratedUnknown(null),
@ -2064,7 +2186,9 @@ enum TranscodeReason {
@JsonValue('DirectPlayError') @JsonValue('DirectPlayError')
directplayerror('DirectPlayError'), directplayerror('DirectPlayError'),
@JsonValue('VideoRangeTypeNotSupported') @JsonValue('VideoRangeTypeNotSupported')
videorangetypenotsupported('VideoRangeTypeNotSupported'); videorangetypenotsupported('VideoRangeTypeNotSupported'),
@JsonValue('VideoCodecTagNotSupported')
videocodectagnotsupported('VideoCodecTagNotSupported');
final String? value; final String? value;
@ -2138,7 +2262,9 @@ enum TranscodingInfoTranscodeReasons {
@JsonValue('DirectPlayError') @JsonValue('DirectPlayError')
directplayerror('DirectPlayError'), directplayerror('DirectPlayError'),
@JsonValue('VideoRangeTypeNotSupported') @JsonValue('VideoRangeTypeNotSupported')
videorangetypenotsupported('VideoRangeTypeNotSupported'); videorangetypenotsupported('VideoRangeTypeNotSupported'),
@JsonValue('VideoCodecTagNotSupported')
videocodectagnotsupported('VideoCodecTagNotSupported');
final String? value; final String? value;
@ -5023,62 +5149,6 @@ enum SessionsSessionIdViewingPostItemType {
const SessionsSessionIdViewingPostItemType(this.value); const SessionsSessionIdViewingPostItemType(this.value);
} }
enum EpisodeIdIntroTimestampsGetMode {
@JsonValue(null)
swaggerGeneratedUnknown(null),
@JsonValue('Introduction')
introduction('Introduction'),
@JsonValue('Credits')
credits('Credits');
final String? value;
const EpisodeIdIntroTimestampsGetMode(this.value);
}
enum EpisodeIdIntroTimestampsV1GetMode {
@JsonValue(null)
swaggerGeneratedUnknown(null),
@JsonValue('Introduction')
introduction('Introduction'),
@JsonValue('Credits')
credits('Credits');
final String? value;
const EpisodeIdIntroTimestampsV1GetMode(this.value);
}
enum IntrosAllGetMode {
@JsonValue(null)
swaggerGeneratedUnknown(null),
@JsonValue('Introduction')
introduction('Introduction'),
@JsonValue('Credits')
credits('Credits');
final String? value;
const IntrosAllGetMode(this.value);
}
enum IntrosEraseTimestampsPostMode {
@JsonValue(null)
swaggerGeneratedUnknown(null),
@JsonValue('Introduction')
introduction('Introduction'),
@JsonValue('Credits')
credits('Credits');
final String? value;
const IntrosEraseTimestampsPostMode(this.value);
}
enum ShowsSeriesIdEpisodesGetSortBy { enum ShowsSeriesIdEpisodesGetSortBy {
@JsonValue(null) @JsonValue(null)
swaggerGeneratedUnknown(null), swaggerGeneratedUnknown(null),

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,47 +0,0 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first, invalid_annotation_target
import 'package:freezed_annotation/freezed_annotation.dart';
part 'intro_skip_model.freezed.dart';
part 'intro_skip_model.g.dart';
@freezed
class IntroOutSkipModel with _$IntroOutSkipModel {
const IntroOutSkipModel._();
factory IntroOutSkipModel({
IntroSkipModel? intro,
IntroSkipModel? credits,
}) = _IntroOutSkipModel;
factory IntroOutSkipModel.fromJson(Map<String, dynamic> json) => _$IntroOutSkipModelFromJson(json);
bool introInRange(Duration position) {
if (intro == null) return false;
return (position.compareTo(intro!.showTime) >= 0 && position.compareTo(intro!.hideTime) <= 0);
}
bool creditsInRange(Duration position) {
if (credits == null) return false;
return (position.compareTo(credits!.showTime) >= 0 && position.compareTo(credits!.hideTime) <= 0);
}
}
@freezed
class IntroSkipModel with _$IntroSkipModel {
factory IntroSkipModel({
@JsonKey(name: "EpisodeId") required String id,
@JsonKey(name: "Valid") required bool valid,
@JsonKey(name: "IntroStart", fromJson: _durationFromMilliseconds, toJson: _durationToMilliseconds)
required Duration start,
@JsonKey(name: "IntroEnd", fromJson: _durationFromMilliseconds, toJson: _durationToMilliseconds)
required Duration end,
@JsonKey(name: "ShowSkipPromptAt", fromJson: _durationFromMilliseconds, toJson: _durationToMilliseconds)
required Duration showTime,
@JsonKey(name: "HideSkipPromptAt", fromJson: _durationFromMilliseconds, toJson: _durationToMilliseconds)
required Duration hideTime,
}) = _IntroSkipModel;
factory IntroSkipModel.fromJson(Map<String, dynamic> json) => _$IntroSkipModelFromJson(json);
}
Duration _durationFromMilliseconds(num milliseconds) => Duration(milliseconds: (milliseconds * 1000).toInt());
num _durationToMilliseconds(Duration duration) => duration.inMilliseconds.toDouble() / 1000.0;

View file

@ -1,595 +0,0 @@
// 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 'intro_skip_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');
IntroOutSkipModel _$IntroOutSkipModelFromJson(Map<String, dynamic> json) {
return _IntroOutSkipModel.fromJson(json);
}
/// @nodoc
mixin _$IntroOutSkipModel {
IntroSkipModel? get intro => throw _privateConstructorUsedError;
IntroSkipModel? get credits => throw _privateConstructorUsedError;
/// Serializes this IntroOutSkipModel to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of IntroOutSkipModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$IntroOutSkipModelCopyWith<IntroOutSkipModel> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $IntroOutSkipModelCopyWith<$Res> {
factory $IntroOutSkipModelCopyWith(
IntroOutSkipModel value, $Res Function(IntroOutSkipModel) then) =
_$IntroOutSkipModelCopyWithImpl<$Res, IntroOutSkipModel>;
@useResult
$Res call({IntroSkipModel? intro, IntroSkipModel? credits});
$IntroSkipModelCopyWith<$Res>? get intro;
$IntroSkipModelCopyWith<$Res>? get credits;
}
/// @nodoc
class _$IntroOutSkipModelCopyWithImpl<$Res, $Val extends IntroOutSkipModel>
implements $IntroOutSkipModelCopyWith<$Res> {
_$IntroOutSkipModelCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of IntroOutSkipModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? intro = freezed,
Object? credits = freezed,
}) {
return _then(_value.copyWith(
intro: freezed == intro
? _value.intro
: intro // ignore: cast_nullable_to_non_nullable
as IntroSkipModel?,
credits: freezed == credits
? _value.credits
: credits // ignore: cast_nullable_to_non_nullable
as IntroSkipModel?,
) as $Val);
}
/// Create a copy of IntroOutSkipModel
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$IntroSkipModelCopyWith<$Res>? get intro {
if (_value.intro == null) {
return null;
}
return $IntroSkipModelCopyWith<$Res>(_value.intro!, (value) {
return _then(_value.copyWith(intro: value) as $Val);
});
}
/// Create a copy of IntroOutSkipModel
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$IntroSkipModelCopyWith<$Res>? get credits {
if (_value.credits == null) {
return null;
}
return $IntroSkipModelCopyWith<$Res>(_value.credits!, (value) {
return _then(_value.copyWith(credits: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$IntroOutSkipModelImplCopyWith<$Res>
implements $IntroOutSkipModelCopyWith<$Res> {
factory _$$IntroOutSkipModelImplCopyWith(_$IntroOutSkipModelImpl value,
$Res Function(_$IntroOutSkipModelImpl) then) =
__$$IntroOutSkipModelImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({IntroSkipModel? intro, IntroSkipModel? credits});
@override
$IntroSkipModelCopyWith<$Res>? get intro;
@override
$IntroSkipModelCopyWith<$Res>? get credits;
}
/// @nodoc
class __$$IntroOutSkipModelImplCopyWithImpl<$Res>
extends _$IntroOutSkipModelCopyWithImpl<$Res, _$IntroOutSkipModelImpl>
implements _$$IntroOutSkipModelImplCopyWith<$Res> {
__$$IntroOutSkipModelImplCopyWithImpl(_$IntroOutSkipModelImpl _value,
$Res Function(_$IntroOutSkipModelImpl) _then)
: super(_value, _then);
/// Create a copy of IntroOutSkipModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? intro = freezed,
Object? credits = freezed,
}) {
return _then(_$IntroOutSkipModelImpl(
intro: freezed == intro
? _value.intro
: intro // ignore: cast_nullable_to_non_nullable
as IntroSkipModel?,
credits: freezed == credits
? _value.credits
: credits // ignore: cast_nullable_to_non_nullable
as IntroSkipModel?,
));
}
}
/// @nodoc
@JsonSerializable()
class _$IntroOutSkipModelImpl extends _IntroOutSkipModel {
_$IntroOutSkipModelImpl({this.intro, this.credits}) : super._();
factory _$IntroOutSkipModelImpl.fromJson(Map<String, dynamic> json) =>
_$$IntroOutSkipModelImplFromJson(json);
@override
final IntroSkipModel? intro;
@override
final IntroSkipModel? credits;
@override
String toString() {
return 'IntroOutSkipModel(intro: $intro, credits: $credits)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$IntroOutSkipModelImpl &&
(identical(other.intro, intro) || other.intro == intro) &&
(identical(other.credits, credits) || other.credits == credits));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, intro, credits);
/// Create a copy of IntroOutSkipModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$IntroOutSkipModelImplCopyWith<_$IntroOutSkipModelImpl> get copyWith =>
__$$IntroOutSkipModelImplCopyWithImpl<_$IntroOutSkipModelImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$IntroOutSkipModelImplToJson(
this,
);
}
}
abstract class _IntroOutSkipModel extends IntroOutSkipModel {
factory _IntroOutSkipModel(
{final IntroSkipModel? intro,
final IntroSkipModel? credits}) = _$IntroOutSkipModelImpl;
_IntroOutSkipModel._() : super._();
factory _IntroOutSkipModel.fromJson(Map<String, dynamic> json) =
_$IntroOutSkipModelImpl.fromJson;
@override
IntroSkipModel? get intro;
@override
IntroSkipModel? get credits;
/// Create a copy of IntroOutSkipModel
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$IntroOutSkipModelImplCopyWith<_$IntroOutSkipModelImpl> get copyWith =>
throw _privateConstructorUsedError;
}
IntroSkipModel _$IntroSkipModelFromJson(Map<String, dynamic> json) {
return _IntroSkipModel.fromJson(json);
}
/// @nodoc
mixin _$IntroSkipModel {
@JsonKey(name: "EpisodeId")
String get id => throw _privateConstructorUsedError;
@JsonKey(name: "Valid")
bool get valid => throw _privateConstructorUsedError;
@JsonKey(
name: "IntroStart",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration get start => throw _privateConstructorUsedError;
@JsonKey(
name: "IntroEnd",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration get end => throw _privateConstructorUsedError;
@JsonKey(
name: "ShowSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration get showTime => throw _privateConstructorUsedError;
@JsonKey(
name: "HideSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration get hideTime => throw _privateConstructorUsedError;
/// Serializes this IntroSkipModel to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of IntroSkipModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$IntroSkipModelCopyWith<IntroSkipModel> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $IntroSkipModelCopyWith<$Res> {
factory $IntroSkipModelCopyWith(
IntroSkipModel value, $Res Function(IntroSkipModel) then) =
_$IntroSkipModelCopyWithImpl<$Res, IntroSkipModel>;
@useResult
$Res call(
{@JsonKey(name: "EpisodeId") String id,
@JsonKey(name: "Valid") bool valid,
@JsonKey(
name: "IntroStart",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration start,
@JsonKey(
name: "IntroEnd",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration end,
@JsonKey(
name: "ShowSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration showTime,
@JsonKey(
name: "HideSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration hideTime});
}
/// @nodoc
class _$IntroSkipModelCopyWithImpl<$Res, $Val extends IntroSkipModel>
implements $IntroSkipModelCopyWith<$Res> {
_$IntroSkipModelCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of IntroSkipModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? valid = null,
Object? start = null,
Object? end = null,
Object? showTime = null,
Object? hideTime = null,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as String,
valid: null == valid
? _value.valid
: valid // ignore: cast_nullable_to_non_nullable
as bool,
start: null == start
? _value.start
: start // ignore: cast_nullable_to_non_nullable
as Duration,
end: null == end
? _value.end
: end // ignore: cast_nullable_to_non_nullable
as Duration,
showTime: null == showTime
? _value.showTime
: showTime // ignore: cast_nullable_to_non_nullable
as Duration,
hideTime: null == hideTime
? _value.hideTime
: hideTime // ignore: cast_nullable_to_non_nullable
as Duration,
) as $Val);
}
}
/// @nodoc
abstract class _$$IntroSkipModelImplCopyWith<$Res>
implements $IntroSkipModelCopyWith<$Res> {
factory _$$IntroSkipModelImplCopyWith(_$IntroSkipModelImpl value,
$Res Function(_$IntroSkipModelImpl) then) =
__$$IntroSkipModelImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{@JsonKey(name: "EpisodeId") String id,
@JsonKey(name: "Valid") bool valid,
@JsonKey(
name: "IntroStart",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration start,
@JsonKey(
name: "IntroEnd",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration end,
@JsonKey(
name: "ShowSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration showTime,
@JsonKey(
name: "HideSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration hideTime});
}
/// @nodoc
class __$$IntroSkipModelImplCopyWithImpl<$Res>
extends _$IntroSkipModelCopyWithImpl<$Res, _$IntroSkipModelImpl>
implements _$$IntroSkipModelImplCopyWith<$Res> {
__$$IntroSkipModelImplCopyWithImpl(
_$IntroSkipModelImpl _value, $Res Function(_$IntroSkipModelImpl) _then)
: super(_value, _then);
/// Create a copy of IntroSkipModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? valid = null,
Object? start = null,
Object? end = null,
Object? showTime = null,
Object? hideTime = null,
}) {
return _then(_$IntroSkipModelImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as String,
valid: null == valid
? _value.valid
: valid // ignore: cast_nullable_to_non_nullable
as bool,
start: null == start
? _value.start
: start // ignore: cast_nullable_to_non_nullable
as Duration,
end: null == end
? _value.end
: end // ignore: cast_nullable_to_non_nullable
as Duration,
showTime: null == showTime
? _value.showTime
: showTime // ignore: cast_nullable_to_non_nullable
as Duration,
hideTime: null == hideTime
? _value.hideTime
: hideTime // ignore: cast_nullable_to_non_nullable
as Duration,
));
}
}
/// @nodoc
@JsonSerializable()
class _$IntroSkipModelImpl implements _IntroSkipModel {
_$IntroSkipModelImpl(
{@JsonKey(name: "EpisodeId") required this.id,
@JsonKey(name: "Valid") required this.valid,
@JsonKey(
name: "IntroStart",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
required this.start,
@JsonKey(
name: "IntroEnd",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
required this.end,
@JsonKey(
name: "ShowSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
required this.showTime,
@JsonKey(
name: "HideSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
required this.hideTime});
factory _$IntroSkipModelImpl.fromJson(Map<String, dynamic> json) =>
_$$IntroSkipModelImplFromJson(json);
@override
@JsonKey(name: "EpisodeId")
final String id;
@override
@JsonKey(name: "Valid")
final bool valid;
@override
@JsonKey(
name: "IntroStart",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
final Duration start;
@override
@JsonKey(
name: "IntroEnd",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
final Duration end;
@override
@JsonKey(
name: "ShowSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
final Duration showTime;
@override
@JsonKey(
name: "HideSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
final Duration hideTime;
@override
String toString() {
return 'IntroSkipModel(id: $id, valid: $valid, start: $start, end: $end, showTime: $showTime, hideTime: $hideTime)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$IntroSkipModelImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.valid, valid) || other.valid == valid) &&
(identical(other.start, start) || other.start == start) &&
(identical(other.end, end) || other.end == end) &&
(identical(other.showTime, showTime) ||
other.showTime == showTime) &&
(identical(other.hideTime, hideTime) ||
other.hideTime == hideTime));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode =>
Object.hash(runtimeType, id, valid, start, end, showTime, hideTime);
/// Create a copy of IntroSkipModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$IntroSkipModelImplCopyWith<_$IntroSkipModelImpl> get copyWith =>
__$$IntroSkipModelImplCopyWithImpl<_$IntroSkipModelImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$IntroSkipModelImplToJson(
this,
);
}
}
abstract class _IntroSkipModel implements IntroSkipModel {
factory _IntroSkipModel(
{@JsonKey(name: "EpisodeId") required final String id,
@JsonKey(name: "Valid") required final bool valid,
@JsonKey(
name: "IntroStart",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
required final Duration start,
@JsonKey(
name: "IntroEnd",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
required final Duration end,
@JsonKey(
name: "ShowSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
required final Duration showTime,
@JsonKey(
name: "HideSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
required final Duration hideTime}) = _$IntroSkipModelImpl;
factory _IntroSkipModel.fromJson(Map<String, dynamic> json) =
_$IntroSkipModelImpl.fromJson;
@override
@JsonKey(name: "EpisodeId")
String get id;
@override
@JsonKey(name: "Valid")
bool get valid;
@override
@JsonKey(
name: "IntroStart",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration get start;
@override
@JsonKey(
name: "IntroEnd",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration get end;
@override
@JsonKey(
name: "ShowSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration get showTime;
@override
@JsonKey(
name: "HideSkipPromptAt",
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration get hideTime;
/// Create a copy of IntroSkipModel
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$IntroSkipModelImplCopyWith<_$IntroSkipModelImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View file

@ -1,46 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'intro_skip_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$IntroOutSkipModelImpl _$$IntroOutSkipModelImplFromJson(
Map<String, dynamic> json) =>
_$IntroOutSkipModelImpl(
intro: json['intro'] == null
? null
: IntroSkipModel.fromJson(json['intro'] as Map<String, dynamic>),
credits: json['credits'] == null
? null
: IntroSkipModel.fromJson(json['credits'] as Map<String, dynamic>),
);
Map<String, dynamic> _$$IntroOutSkipModelImplToJson(
_$IntroOutSkipModelImpl instance) =>
<String, dynamic>{
'intro': instance.intro,
'credits': instance.credits,
};
_$IntroSkipModelImpl _$$IntroSkipModelImplFromJson(Map<String, dynamic> json) =>
_$IntroSkipModelImpl(
id: json['EpisodeId'] as String,
valid: json['Valid'] as bool,
start: _durationFromMilliseconds(json['IntroStart'] as num),
end: _durationFromMilliseconds(json['IntroEnd'] as num),
showTime: _durationFromMilliseconds(json['ShowSkipPromptAt'] as num),
hideTime: _durationFromMilliseconds(json['HideSkipPromptAt'] as num),
);
Map<String, dynamic> _$$IntroSkipModelImplToJson(
_$IntroSkipModelImpl instance) =>
<String, dynamic>{
'EpisodeId': instance.id,
'Valid': instance.valid,
'IntroStart': _durationToMilliseconds(instance.start),
'IntroEnd': _durationToMilliseconds(instance.end),
'ShowSkipPromptAt': _durationToMilliseconds(instance.showTime),
'HideSkipPromptAt': _durationToMilliseconds(instance.hideTime),
};

View file

@ -0,0 +1,79 @@
import 'package:flutter/material.dart';
import 'package:collection/collection.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart' as dto;
part 'media_segments_model.freezed.dart';
part 'media_segments_model.g.dart';
@freezed
class MediaSegmentsModel with _$MediaSegmentsModel {
const MediaSegmentsModel._();
factory MediaSegmentsModel({
@Default([]) List<MediaSegment> segments,
}) = _MediaSegmentsModel;
factory MediaSegmentsModel.fromJson(Map<String, dynamic> json) => _$MediaSegmentsModelFromJson(json);
MediaSegment? get intro => segments.firstWhereOrNull((element) => element.type == MediaSegmentType.intro);
MediaSegment? get outro => segments.firstWhereOrNull((element) => element.type == MediaSegmentType.outro);
}
@freezed
class MediaSegment with _$MediaSegment {
const MediaSegment._();
factory MediaSegment({
required MediaSegmentType type,
required Duration start,
required Duration end,
}) = _MediaSegment;
factory MediaSegment.fromJson(Map<String, dynamic> json) => _$MediaSegmentFromJson(json);
bool inRange(Duration position) => (position.compareTo(start) >= 0 && position.compareTo(end) <= 0);
}
enum MediaSegmentType {
unknown,
commercial,
preview,
recap,
outro,
intro;
Color get color => switch (this) {
MediaSegmentType.unknown => Colors.black,
MediaSegmentType.commercial => Colors.purpleAccent,
MediaSegmentType.preview => Colors.deepOrangeAccent,
MediaSegmentType.recap => Colors.lightBlueAccent,
MediaSegmentType.outro => Colors.yellowAccent,
MediaSegmentType.intro => Colors.greenAccent,
};
static MediaSegmentType fromDto(dto.MediaSegmentType? value) {
return switch (value) {
dto.MediaSegmentType.swaggerGeneratedUnknown => MediaSegmentType.unknown,
dto.MediaSegmentType.unknown => MediaSegmentType.unknown,
dto.MediaSegmentType.commercial => MediaSegmentType.commercial,
dto.MediaSegmentType.preview => MediaSegmentType.preview,
dto.MediaSegmentType.recap => MediaSegmentType.recap,
dto.MediaSegmentType.outro => MediaSegmentType.outro,
dto.MediaSegmentType.intro => MediaSegmentType.intro,
null => MediaSegmentType.unknown,
};
}
}
extension MediaSegmentExtension on dto.MediaSegmentDto {
MediaSegment get toSegment => MediaSegment(
type: MediaSegmentType.fromDto(type),
start: _durationToMilliseconds(startTicks ?? 0),
end: _durationToMilliseconds(endTicks ?? 0),
);
}
Duration _durationToMilliseconds(num milliseconds) => Duration(milliseconds: (milliseconds ~/ 10000));

View file

@ -0,0 +1,363 @@
// 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 'media_segments_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');
MediaSegmentsModel _$MediaSegmentsModelFromJson(Map<String, dynamic> json) {
return _MediaSegmentsModel.fromJson(json);
}
/// @nodoc
mixin _$MediaSegmentsModel {
List<MediaSegment> get segments => throw _privateConstructorUsedError;
/// Serializes this MediaSegmentsModel to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of MediaSegmentsModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$MediaSegmentsModelCopyWith<MediaSegmentsModel> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $MediaSegmentsModelCopyWith<$Res> {
factory $MediaSegmentsModelCopyWith(
MediaSegmentsModel value, $Res Function(MediaSegmentsModel) then) =
_$MediaSegmentsModelCopyWithImpl<$Res, MediaSegmentsModel>;
@useResult
$Res call({List<MediaSegment> segments});
}
/// @nodoc
class _$MediaSegmentsModelCopyWithImpl<$Res, $Val extends MediaSegmentsModel>
implements $MediaSegmentsModelCopyWith<$Res> {
_$MediaSegmentsModelCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of MediaSegmentsModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? segments = null,
}) {
return _then(_value.copyWith(
segments: null == segments
? _value.segments
: segments // ignore: cast_nullable_to_non_nullable
as List<MediaSegment>,
) as $Val);
}
}
/// @nodoc
abstract class _$$MediaSegmentsModelImplCopyWith<$Res>
implements $MediaSegmentsModelCopyWith<$Res> {
factory _$$MediaSegmentsModelImplCopyWith(_$MediaSegmentsModelImpl value,
$Res Function(_$MediaSegmentsModelImpl) then) =
__$$MediaSegmentsModelImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({List<MediaSegment> segments});
}
/// @nodoc
class __$$MediaSegmentsModelImplCopyWithImpl<$Res>
extends _$MediaSegmentsModelCopyWithImpl<$Res, _$MediaSegmentsModelImpl>
implements _$$MediaSegmentsModelImplCopyWith<$Res> {
__$$MediaSegmentsModelImplCopyWithImpl(_$MediaSegmentsModelImpl _value,
$Res Function(_$MediaSegmentsModelImpl) _then)
: super(_value, _then);
/// Create a copy of MediaSegmentsModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? segments = null,
}) {
return _then(_$MediaSegmentsModelImpl(
segments: null == segments
? _value._segments
: segments // ignore: cast_nullable_to_non_nullable
as List<MediaSegment>,
));
}
}
/// @nodoc
@JsonSerializable()
class _$MediaSegmentsModelImpl extends _MediaSegmentsModel {
_$MediaSegmentsModelImpl({final List<MediaSegment> segments = const []})
: _segments = segments,
super._();
factory _$MediaSegmentsModelImpl.fromJson(Map<String, dynamic> json) =>
_$$MediaSegmentsModelImplFromJson(json);
final List<MediaSegment> _segments;
@override
@JsonKey()
List<MediaSegment> get segments {
if (_segments is EqualUnmodifiableListView) return _segments;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_segments);
}
@override
String toString() {
return 'MediaSegmentsModel(segments: $segments)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$MediaSegmentsModelImpl &&
const DeepCollectionEquality().equals(other._segments, _segments));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode =>
Object.hash(runtimeType, const DeepCollectionEquality().hash(_segments));
/// Create a copy of MediaSegmentsModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$MediaSegmentsModelImplCopyWith<_$MediaSegmentsModelImpl> get copyWith =>
__$$MediaSegmentsModelImplCopyWithImpl<_$MediaSegmentsModelImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$MediaSegmentsModelImplToJson(
this,
);
}
}
abstract class _MediaSegmentsModel extends MediaSegmentsModel {
factory _MediaSegmentsModel({final List<MediaSegment> segments}) =
_$MediaSegmentsModelImpl;
_MediaSegmentsModel._() : super._();
factory _MediaSegmentsModel.fromJson(Map<String, dynamic> json) =
_$MediaSegmentsModelImpl.fromJson;
@override
List<MediaSegment> get segments;
/// Create a copy of MediaSegmentsModel
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$MediaSegmentsModelImplCopyWith<_$MediaSegmentsModelImpl> get copyWith =>
throw _privateConstructorUsedError;
}
MediaSegment _$MediaSegmentFromJson(Map<String, dynamic> json) {
return _MediaSegment.fromJson(json);
}
/// @nodoc
mixin _$MediaSegment {
MediaSegmentType get type => throw _privateConstructorUsedError;
Duration get start => throw _privateConstructorUsedError;
Duration get end => throw _privateConstructorUsedError;
/// Serializes this MediaSegment to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of MediaSegment
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$MediaSegmentCopyWith<MediaSegment> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $MediaSegmentCopyWith<$Res> {
factory $MediaSegmentCopyWith(
MediaSegment value, $Res Function(MediaSegment) then) =
_$MediaSegmentCopyWithImpl<$Res, MediaSegment>;
@useResult
$Res call({MediaSegmentType type, Duration start, Duration end});
}
/// @nodoc
class _$MediaSegmentCopyWithImpl<$Res, $Val extends MediaSegment>
implements $MediaSegmentCopyWith<$Res> {
_$MediaSegmentCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of MediaSegment
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? type = null,
Object? start = null,
Object? end = null,
}) {
return _then(_value.copyWith(
type: null == type
? _value.type
: type // ignore: cast_nullable_to_non_nullable
as MediaSegmentType,
start: null == start
? _value.start
: start // ignore: cast_nullable_to_non_nullable
as Duration,
end: null == end
? _value.end
: end // ignore: cast_nullable_to_non_nullable
as Duration,
) as $Val);
}
}
/// @nodoc
abstract class _$$MediaSegmentImplCopyWith<$Res>
implements $MediaSegmentCopyWith<$Res> {
factory _$$MediaSegmentImplCopyWith(
_$MediaSegmentImpl value, $Res Function(_$MediaSegmentImpl) then) =
__$$MediaSegmentImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({MediaSegmentType type, Duration start, Duration end});
}
/// @nodoc
class __$$MediaSegmentImplCopyWithImpl<$Res>
extends _$MediaSegmentCopyWithImpl<$Res, _$MediaSegmentImpl>
implements _$$MediaSegmentImplCopyWith<$Res> {
__$$MediaSegmentImplCopyWithImpl(
_$MediaSegmentImpl _value, $Res Function(_$MediaSegmentImpl) _then)
: super(_value, _then);
/// Create a copy of MediaSegment
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? type = null,
Object? start = null,
Object? end = null,
}) {
return _then(_$MediaSegmentImpl(
type: null == type
? _value.type
: type // ignore: cast_nullable_to_non_nullable
as MediaSegmentType,
start: null == start
? _value.start
: start // ignore: cast_nullable_to_non_nullable
as Duration,
end: null == end
? _value.end
: end // ignore: cast_nullable_to_non_nullable
as Duration,
));
}
}
/// @nodoc
@JsonSerializable()
class _$MediaSegmentImpl extends _MediaSegment {
_$MediaSegmentImpl(
{required this.type, required this.start, required this.end})
: super._();
factory _$MediaSegmentImpl.fromJson(Map<String, dynamic> json) =>
_$$MediaSegmentImplFromJson(json);
@override
final MediaSegmentType type;
@override
final Duration start;
@override
final Duration end;
@override
String toString() {
return 'MediaSegment(type: $type, start: $start, end: $end)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$MediaSegmentImpl &&
(identical(other.type, type) || other.type == type) &&
(identical(other.start, start) || other.start == start) &&
(identical(other.end, end) || other.end == end));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, type, start, end);
/// Create a copy of MediaSegment
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$MediaSegmentImplCopyWith<_$MediaSegmentImpl> get copyWith =>
__$$MediaSegmentImplCopyWithImpl<_$MediaSegmentImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$MediaSegmentImplToJson(
this,
);
}
}
abstract class _MediaSegment extends MediaSegment {
factory _MediaSegment(
{required final MediaSegmentType type,
required final Duration start,
required final Duration end}) = _$MediaSegmentImpl;
_MediaSegment._() : super._();
factory _MediaSegment.fromJson(Map<String, dynamic> json) =
_$MediaSegmentImpl.fromJson;
@override
MediaSegmentType get type;
@override
Duration get start;
@override
Duration get end;
/// Create a copy of MediaSegment
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$MediaSegmentImplCopyWith<_$MediaSegmentImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View file

@ -0,0 +1,45 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'media_segments_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$MediaSegmentsModelImpl _$$MediaSegmentsModelImplFromJson(
Map<String, dynamic> json) =>
_$MediaSegmentsModelImpl(
segments: (json['segments'] as List<dynamic>?)
?.map((e) => MediaSegment.fromJson(e as Map<String, dynamic>))
.toList() ??
const [],
);
Map<String, dynamic> _$$MediaSegmentsModelImplToJson(
_$MediaSegmentsModelImpl instance) =>
<String, dynamic>{
'segments': instance.segments,
};
_$MediaSegmentImpl _$$MediaSegmentImplFromJson(Map<String, dynamic> json) =>
_$MediaSegmentImpl(
type: $enumDecode(_$MediaSegmentTypeEnumMap, json['type']),
start: Duration(microseconds: (json['start'] as num).toInt()),
end: Duration(microseconds: (json['end'] as num).toInt()),
);
Map<String, dynamic> _$$MediaSegmentImplToJson(_$MediaSegmentImpl instance) =>
<String, dynamic>{
'type': _$MediaSegmentTypeEnumMap[instance.type]!,
'start': instance.start.inMicroseconds,
'end': instance.end.inMicroseconds,
};
const _$MediaSegmentTypeEnumMap = {
MediaSegmentType.unknown: 'unknown',
MediaSegmentType.commercial: 'commercial',
MediaSegmentType.preview: 'preview',
MediaSegmentType.recap: 'recap',
MediaSegmentType.outro: 'outro',
MediaSegmentType.intro: 'intro',
};

View file

@ -5,7 +5,7 @@ import 'package:media_kit/media_kit.dart';
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart'; import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/items/chapters_model.dart'; import 'package:fladder/models/items/chapters_model.dart';
import 'package:fladder/models/items/intro_skip_model.dart'; import 'package:fladder/models/items/media_segments_model.dart';
import 'package:fladder/models/items/media_streams_model.dart'; import 'package:fladder/models/items/media_streams_model.dart';
import 'package:fladder/models/items/trick_play_model.dart'; import 'package:fladder/models/items/trick_play_model.dart';
import 'package:fladder/models/playback/playback_model.dart'; import 'package:fladder/models/playback/playback_model.dart';
@ -23,7 +23,7 @@ class DirectPlaybackModel implements PlaybackModel {
required this.media, required this.media,
required this.playbackInfo, required this.playbackInfo,
this.mediaStreams, this.mediaStreams,
this.introSkipModel, this.mediaSegments,
this.chapters, this.chapters,
this.trickPlay, this.trickPlay,
this.queue = const [], this.queue = const [],
@ -42,7 +42,7 @@ class DirectPlaybackModel implements PlaybackModel {
final MediaStreamsModel? mediaStreams; final MediaStreamsModel? mediaStreams;
@override @override
final IntroOutSkipModel? introSkipModel; final MediaSegmentsModel? mediaSegments;
@override @override
final List<Chapter>? chapters; final List<Chapter>? chapters;
@ -180,7 +180,7 @@ class DirectPlaybackModel implements PlaybackModel {
ValueGetter<Duration>? lastPosition, ValueGetter<Duration>? lastPosition,
PlaybackInfoResponse? playbackInfo, PlaybackInfoResponse? playbackInfo,
ValueGetter<MediaStreamsModel?>? mediaStreams, ValueGetter<MediaStreamsModel?>? mediaStreams,
ValueGetter<IntroOutSkipModel?>? introSkipModel, ValueGetter<MediaSegmentsModel?>? mediaSegments,
ValueGetter<List<Chapter>?>? chapters, ValueGetter<List<Chapter>?>? chapters,
ValueGetter<TrickPlayModel?>? trickPlay, ValueGetter<TrickPlayModel?>? trickPlay,
List<ItemBaseModel>? queue, List<ItemBaseModel>? queue,
@ -190,7 +190,7 @@ class DirectPlaybackModel implements PlaybackModel {
media: media != null ? media() : this.media, media: media != null ? media() : this.media,
playbackInfo: playbackInfo ?? this.playbackInfo, playbackInfo: playbackInfo ?? this.playbackInfo,
mediaStreams: mediaStreams != null ? mediaStreams() : this.mediaStreams, mediaStreams: mediaStreams != null ? mediaStreams() : this.mediaStreams,
introSkipModel: introSkipModel != null ? introSkipModel() : this.introSkipModel, mediaSegments: mediaSegments != null ? mediaSegments() : this.mediaSegments,
chapters: chapters != null ? chapters() : this.chapters, chapters: chapters != null ? chapters() : this.chapters,
trickPlay: trickPlay != null ? trickPlay() : this.trickPlay, trickPlay: trickPlay != null ? trickPlay() : this.trickPlay,
queue: queue ?? this.queue, queue: queue ?? this.queue,

View file

@ -1,21 +1,21 @@
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:media_kit/media_kit.dart';
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart'; import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/items/chapters_model.dart';
import 'package:fladder/models/items/media_segments_model.dart';
import 'package:fladder/models/items/media_streams_model.dart';
import 'package:fladder/models/items/trick_play_model.dart'; import 'package:fladder/models/items/trick_play_model.dart';
import 'package:fladder/models/playback/playback_model.dart';
import 'package:fladder/models/syncing/sync_item.dart'; import 'package:fladder/models/syncing/sync_item.dart';
import 'package:fladder/providers/sync_provider.dart';
import 'package:fladder/util/duration_extensions.dart';
import 'package:fladder/util/list_extensions.dart'; import 'package:fladder/util/list_extensions.dart';
import 'package:fladder/wrappers/media_control_wrapper.dart' import 'package:fladder/wrappers/media_control_wrapper.dart'
if (dart.library.html) 'package:fladder/wrappers/media_control_wrapper_web.dart'; if (dart.library.html) 'package:fladder/wrappers/media_control_wrapper_web.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:media_kit/media_kit.dart';
import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/items/chapters_model.dart';
import 'package:fladder/models/items/intro_skip_model.dart';
import 'package:fladder/models/items/media_streams_model.dart';
import 'package:fladder/models/playback/playback_model.dart';
import 'package:fladder/providers/sync_provider.dart';
import 'package:fladder/util/duration_extensions.dart';
class OfflinePlaybackModel implements PlaybackModel { class OfflinePlaybackModel implements PlaybackModel {
OfflinePlaybackModel({ OfflinePlaybackModel({
@ -24,7 +24,7 @@ class OfflinePlaybackModel implements PlaybackModel {
required this.syncedItem, required this.syncedItem,
this.mediaStreams, this.mediaStreams,
this.playbackInfo, this.playbackInfo,
this.introSkipModel, this.mediaSegments,
this.trickPlay, this.trickPlay,
this.queue = const [], this.queue = const [],
this.syncedQueue = const [], this.syncedQueue = const [],
@ -45,7 +45,7 @@ class OfflinePlaybackModel implements PlaybackModel {
final MediaStreamsModel? mediaStreams; final MediaStreamsModel? mediaStreams;
@override @override
final IntroOutSkipModel? introSkipModel; final MediaSegmentsModel? mediaSegments;
@override @override
List<Chapter>? get chapters => syncedItem.chapters; List<Chapter>? get chapters => syncedItem.chapters;
@ -156,7 +156,7 @@ class OfflinePlaybackModel implements PlaybackModel {
ValueGetter<Media?>? media, ValueGetter<Media?>? media,
SyncedItem? syncedItem, SyncedItem? syncedItem,
ValueGetter<MediaStreamsModel?>? mediaStreams, ValueGetter<MediaStreamsModel?>? mediaStreams,
ValueGetter<IntroOutSkipModel?>? introSkipModel, ValueGetter<MediaSegmentsModel?>? mediaSegments,
ValueGetter<TrickPlayModel?>? trickPlay, ValueGetter<TrickPlayModel?>? trickPlay,
List<ItemBaseModel>? queue, List<ItemBaseModel>? queue,
List<SyncedItem>? syncedQueue, List<SyncedItem>? syncedQueue,
@ -166,7 +166,7 @@ class OfflinePlaybackModel implements PlaybackModel {
media: media != null ? media() : this.media, media: media != null ? media() : this.media,
syncedItem: syncedItem ?? this.syncedItem, syncedItem: syncedItem ?? this.syncedItem,
mediaStreams: mediaStreams != null ? mediaStreams() : this.mediaStreams, mediaStreams: mediaStreams != null ? mediaStreams() : this.mediaStreams,
introSkipModel: introSkipModel != null ? introSkipModel() : this.introSkipModel, mediaSegments: mediaSegments != null ? mediaSegments() : this.mediaSegments,
trickPlay: trickPlay != null ? trickPlay() : this.trickPlay, trickPlay: trickPlay != null ? trickPlay() : this.trickPlay,
queue: queue ?? this.queue, queue: queue ?? this.queue,
syncedQueue: syncedQueue ?? this.syncedQueue, syncedQueue: syncedQueue ?? this.syncedQueue,

View file

@ -9,7 +9,7 @@ import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/items/chapters_model.dart'; import 'package:fladder/models/items/chapters_model.dart';
import 'package:fladder/models/items/episode_model.dart'; import 'package:fladder/models/items/episode_model.dart';
import 'package:fladder/models/items/intro_skip_model.dart'; import 'package:fladder/models/items/media_segments_model.dart';
import 'package:fladder/models/items/media_streams_model.dart'; import 'package:fladder/models/items/media_streams_model.dart';
import 'package:fladder/models/items/season_model.dart'; import 'package:fladder/models/items/season_model.dart';
import 'package:fladder/models/items/series_model.dart'; import 'package:fladder/models/items/series_model.dart';
@ -43,7 +43,7 @@ abstract class PlaybackModel {
final ItemBaseModel item = throw UnimplementedError(); final ItemBaseModel item = throw UnimplementedError();
final Media? media = throw UnimplementedError(); final Media? media = throw UnimplementedError();
final List<ItemBaseModel> queue = const []; final List<ItemBaseModel> queue = const [];
final IntroOutSkipModel? introSkipModel = null; final MediaSegmentsModel? mediaSegments = null;
final PlaybackInfoResponse? playbackInfo = throw UnimplementedError(); final PlaybackInfoResponse? playbackInfo = throw UnimplementedError();
List<Chapter>? get chapters; List<Chapter>? get chapters;
@ -118,7 +118,7 @@ class PlaybackModelHelper {
item: syncedItemModel, item: syncedItemModel,
syncedItem: syncedItem, syncedItem: syncedItem,
trickPlay: syncedItem.trickPlayModel, trickPlay: syncedItem.trickPlayModel,
introSkipModel: syncedItem.introOutSkipModel, mediaSegments: syncedItem.mediaSegments,
media: Media(syncedItem.videoFile.path), media: Media(syncedItem.videoFile.path),
queue: itemQueue.whereNotNull().toList(), queue: itemQueue.whereNotNull().toList(),
syncedQueue: children, syncedQueue: children,
@ -188,7 +188,7 @@ class PlaybackModelHelper {
defaultSubStreamIndex: streamModel?.defaultSubStreamIndex, defaultSubStreamIndex: streamModel?.defaultSubStreamIndex,
); );
final intro = await api.introSkipGet(id: item.id); final mediaSegments = await api.mediaSegmentsGet(id: item.id);
final trickPlay = (await api.getTrickPlay(item: fullItem.body, ref: ref))?.body; final trickPlay = (await api.getTrickPlay(item: fullItem.body, ref: ref))?.body;
final chapters = fullItem.body?.overview.chapters ?? []; final chapters = fullItem.body?.overview.chapters ?? [];
@ -214,7 +214,7 @@ class PlaybackModelHelper {
return DirectPlaybackModel( return DirectPlaybackModel(
item: fullItem.body ?? item, item: fullItem.body ?? item,
queue: queue, queue: queue,
introSkipModel: intro?.body, mediaSegments: mediaSegments?.body,
chapters: chapters, chapters: chapters,
playbackInfo: playbackInfo, playbackInfo: playbackInfo,
trickPlay: trickPlay, trickPlay: trickPlay,
@ -225,7 +225,7 @@ class PlaybackModelHelper {
return TranscodePlaybackModel( return TranscodePlaybackModel(
item: fullItem.body ?? item, item: fullItem.body ?? item,
queue: queue, queue: queue,
introSkipModel: intro?.body, mediaSegments: mediaSegments?.body,
chapters: chapters, chapters: chapters,
trickPlay: trickPlay, trickPlay: trickPlay,
playbackInfo: playbackInfo, playbackInfo: playbackInfo,
@ -343,7 +343,7 @@ class PlaybackModelHelper {
newModel = DirectPlaybackModel( newModel = DirectPlaybackModel(
item: playbackModel.item, item: playbackModel.item,
queue: playbackModel.queue, queue: playbackModel.queue,
introSkipModel: playbackModel.introSkipModel, mediaSegments: playbackModel.mediaSegments,
chapters: playbackModel.chapters, chapters: playbackModel.chapters,
playbackInfo: playbackInfo, playbackInfo: playbackInfo,
trickPlay: playbackModel.trickPlay, trickPlay: playbackModel.trickPlay,
@ -354,7 +354,7 @@ class PlaybackModelHelper {
newModel = TranscodePlaybackModel( newModel = TranscodePlaybackModel(
item: playbackModel.item, item: playbackModel.item,
queue: playbackModel.queue, queue: playbackModel.queue,
introSkipModel: playbackModel.introSkipModel, mediaSegments: playbackModel.mediaSegments,
chapters: playbackModel.chapters, chapters: playbackModel.chapters,
playbackInfo: playbackInfo, playbackInfo: playbackInfo,
trickPlay: playbackModel.trickPlay, trickPlay: playbackModel.trickPlay,

View file

@ -5,7 +5,7 @@ import 'package:media_kit/media_kit.dart';
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart'; import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/items/chapters_model.dart'; import 'package:fladder/models/items/chapters_model.dart';
import 'package:fladder/models/items/intro_skip_model.dart'; import 'package:fladder/models/items/media_segments_model.dart';
import 'package:fladder/models/items/media_streams_model.dart'; import 'package:fladder/models/items/media_streams_model.dart';
import 'package:fladder/models/items/trick_play_model.dart'; import 'package:fladder/models/items/trick_play_model.dart';
import 'package:fladder/models/playback/playback_model.dart'; import 'package:fladder/models/playback/playback_model.dart';
@ -23,7 +23,7 @@ class TranscodePlaybackModel implements PlaybackModel {
required this.media, required this.media,
required this.playbackInfo, required this.playbackInfo,
this.mediaStreams, this.mediaStreams,
this.introSkipModel, this.mediaSegments,
this.chapters, this.chapters,
this.trickPlay, this.trickPlay,
this.queue = const [], this.queue = const [],
@ -42,7 +42,7 @@ class TranscodePlaybackModel implements PlaybackModel {
final MediaStreamsModel? mediaStreams; final MediaStreamsModel? mediaStreams;
@override @override
final IntroOutSkipModel? introSkipModel; final MediaSegmentsModel? mediaSegments;
@override @override
final List<Chapter>? chapters; final List<Chapter>? chapters;
@ -181,7 +181,7 @@ class TranscodePlaybackModel implements PlaybackModel {
ValueGetter<Duration>? lastPosition, ValueGetter<Duration>? lastPosition,
PlaybackInfoResponse? playbackInfo, PlaybackInfoResponse? playbackInfo,
ValueGetter<MediaStreamsModel?>? mediaStreams, ValueGetter<MediaStreamsModel?>? mediaStreams,
ValueGetter<IntroOutSkipModel?>? introSkipModel, ValueGetter<MediaSegmentsModel?>? mediaSegments,
ValueGetter<List<Chapter>?>? chapters, ValueGetter<List<Chapter>?>? chapters,
ValueGetter<TrickPlayModel?>? trickPlay, ValueGetter<TrickPlayModel?>? trickPlay,
List<ItemBaseModel>? queue, List<ItemBaseModel>? queue,
@ -191,7 +191,7 @@ class TranscodePlaybackModel implements PlaybackModel {
media: media != null ? media() : this.media, media: media != null ? media() : this.media,
playbackInfo: playbackInfo ?? this.playbackInfo, playbackInfo: playbackInfo ?? this.playbackInfo,
mediaStreams: mediaStreams != null ? mediaStreams() : this.mediaStreams, mediaStreams: mediaStreams != null ? mediaStreams() : this.mediaStreams,
introSkipModel: introSkipModel != null ? introSkipModel() : this.introSkipModel, mediaSegments: mediaSegments != null ? mediaSegments() : this.mediaSegments,
chapters: chapters != null ? chapters() : this.chapters, chapters: chapters != null ? chapters() : this.chapters,
trickPlay: trickPlay != null ? trickPlay() : this.trickPlay, trickPlay: trickPlay != null ? trickPlay() : this.trickPlay,
queue: queue ?? this.queue, queue: queue ?? this.queue,

View file

@ -35,7 +35,7 @@ class ISyncedItem {
int? fileSize; int? fileSize;
String? videoFileName; String? videoFileName;
String? trickPlayModel; String? trickPlayModel;
String? introOutroSkipModel; String? mediaSegments;
String? images; String? images;
List<String>? chapters; List<String>? chapters;
List<String>? subtitles; List<String>? subtitles;
@ -50,7 +50,7 @@ class ISyncedItem {
this.fileSize, this.fileSize,
this.videoFileName, this.videoFileName,
this.trickPlayModel, this.trickPlayModel,
this.introOutroSkipModel, this.mediaSegments,
this.images, this.images,
this.chapters, this.chapters,
this.subtitles, this.subtitles,
@ -68,8 +68,7 @@ class ISyncedItem {
sortName: syncedItem.sortName, sortName: syncedItem.sortName,
videoFileName: syncedItem.videoFileName, videoFileName: syncedItem.videoFileName,
trickPlayModel: syncedItem.fTrickPlayModel != null ? jsonEncode(syncedItem.fTrickPlayModel?.toJson()) : null, trickPlayModel: syncedItem.fTrickPlayModel != null ? jsonEncode(syncedItem.fTrickPlayModel?.toJson()) : null,
introOutroSkipModel: mediaSegments: syncedItem.mediaSegments != null ? jsonEncode(syncedItem.mediaSegments?.toJson()) : null,
syncedItem.introOutSkipModel != null ? jsonEncode(syncedItem.introOutSkipModel?.toJson()) : null,
images: syncedItem.fImages != null ? jsonEncode(syncedItem.fImages?.toJson()) : null, images: syncedItem.fImages != null ? jsonEncode(syncedItem.fImages?.toJson()) : null,
chapters: syncedItem.fChapters.map((e) => jsonEncode(e.toJson())).toList(), chapters: syncedItem.fChapters.map((e) => jsonEncode(e.toJson())).toList(),
subtitles: syncedItem.subtitles.map((e) => jsonEncode(e.toJson())).toList(), subtitles: syncedItem.subtitles.map((e) => jsonEncode(e.toJson())).toList(),

View file

@ -57,7 +57,7 @@ const ISyncedItemSchema = IsarGeneratedSchema(
type: IsarType.string, type: IsarType.string,
), ),
IsarPropertySchema( IsarPropertySchema(
name: 'introOutroSkipModel', name: 'mediaSegments',
type: IsarType.string, type: IsarType.string,
), ),
IsarPropertySchema( IsarPropertySchema(
@ -141,7 +141,7 @@ int serializeISyncedItem(IsarWriter writer, ISyncedItem object) {
} }
} }
{ {
final value = object.introOutroSkipModel; final value = object.mediaSegments;
if (value == null) { if (value == null) {
IsarCore.writeNull(writer, 10); IsarCore.writeNull(writer, 10);
} else { } else {
@ -218,8 +218,8 @@ ISyncedItem deserializeISyncedItem(IsarReader reader) {
_videoFileName = IsarCore.readString(reader, 8); _videoFileName = IsarCore.readString(reader, 8);
final String? _trickPlayModel; final String? _trickPlayModel;
_trickPlayModel = IsarCore.readString(reader, 9); _trickPlayModel = IsarCore.readString(reader, 9);
final String? _introOutroSkipModel; final String? _mediaSegments;
_introOutroSkipModel = IsarCore.readString(reader, 10); _mediaSegments = IsarCore.readString(reader, 10);
final String? _images; final String? _images;
_images = IsarCore.readString(reader, 11); _images = IsarCore.readString(reader, 11);
final List<String>? _chapters; final List<String>? _chapters;
@ -268,7 +268,7 @@ ISyncedItem deserializeISyncedItem(IsarReader reader) {
fileSize: _fileSize, fileSize: _fileSize,
videoFileName: _videoFileName, videoFileName: _videoFileName,
trickPlayModel: _trickPlayModel, trickPlayModel: _trickPlayModel,
introOutroSkipModel: _introOutroSkipModel, mediaSegments: _mediaSegments,
images: _images, images: _images,
chapters: _chapters, chapters: _chapters,
subtitles: _subtitles, subtitles: _subtitles,
@ -361,7 +361,7 @@ sealed class _ISyncedItemUpdate {
int? fileSize, int? fileSize,
String? videoFileName, String? videoFileName,
String? trickPlayModel, String? trickPlayModel,
String? introOutroSkipModel, String? mediaSegments,
String? images, String? images,
String? userData, String? userData,
}); });
@ -383,7 +383,7 @@ class _ISyncedItemUpdateImpl implements _ISyncedItemUpdate {
Object? fileSize = ignore, Object? fileSize = ignore,
Object? videoFileName = ignore, Object? videoFileName = ignore,
Object? trickPlayModel = ignore, Object? trickPlayModel = ignore,
Object? introOutroSkipModel = ignore, Object? mediaSegments = ignore,
Object? images = ignore, Object? images = ignore,
Object? userData = ignore, Object? userData = ignore,
}) { }) {
@ -398,7 +398,7 @@ class _ISyncedItemUpdateImpl implements _ISyncedItemUpdate {
if (fileSize != ignore) 7: fileSize as int?, if (fileSize != ignore) 7: fileSize as int?,
if (videoFileName != ignore) 8: videoFileName as String?, if (videoFileName != ignore) 8: videoFileName as String?,
if (trickPlayModel != ignore) 9: trickPlayModel as String?, if (trickPlayModel != ignore) 9: trickPlayModel as String?,
if (introOutroSkipModel != ignore) 10: introOutroSkipModel as String?, if (mediaSegments != ignore) 10: mediaSegments as String?,
if (images != ignore) 11: images as String?, if (images != ignore) 11: images as String?,
if (userData != ignore) 14: userData as String?, if (userData != ignore) 14: userData as String?,
}) > }) >
@ -417,7 +417,7 @@ sealed class _ISyncedItemUpdateAll {
int? fileSize, int? fileSize,
String? videoFileName, String? videoFileName,
String? trickPlayModel, String? trickPlayModel,
String? introOutroSkipModel, String? mediaSegments,
String? images, String? images,
String? userData, String? userData,
}); });
@ -439,7 +439,7 @@ class _ISyncedItemUpdateAllImpl implements _ISyncedItemUpdateAll {
Object? fileSize = ignore, Object? fileSize = ignore,
Object? videoFileName = ignore, Object? videoFileName = ignore,
Object? trickPlayModel = ignore, Object? trickPlayModel = ignore,
Object? introOutroSkipModel = ignore, Object? mediaSegments = ignore,
Object? images = ignore, Object? images = ignore,
Object? userData = ignore, Object? userData = ignore,
}) { }) {
@ -452,7 +452,7 @@ class _ISyncedItemUpdateAllImpl implements _ISyncedItemUpdateAll {
if (fileSize != ignore) 7: fileSize as int?, if (fileSize != ignore) 7: fileSize as int?,
if (videoFileName != ignore) 8: videoFileName as String?, if (videoFileName != ignore) 8: videoFileName as String?,
if (trickPlayModel != ignore) 9: trickPlayModel as String?, if (trickPlayModel != ignore) 9: trickPlayModel as String?,
if (introOutroSkipModel != ignore) 10: introOutroSkipModel as String?, if (mediaSegments != ignore) 10: mediaSegments as String?,
if (images != ignore) 11: images as String?, if (images != ignore) 11: images as String?,
if (userData != ignore) 14: userData as String?, if (userData != ignore) 14: userData as String?,
}); });
@ -475,7 +475,7 @@ sealed class _ISyncedItemQueryUpdate {
int? fileSize, int? fileSize,
String? videoFileName, String? videoFileName,
String? trickPlayModel, String? trickPlayModel,
String? introOutroSkipModel, String? mediaSegments,
String? images, String? images,
String? userData, String? userData,
}); });
@ -497,7 +497,7 @@ class _ISyncedItemQueryUpdateImpl implements _ISyncedItemQueryUpdate {
Object? fileSize = ignore, Object? fileSize = ignore,
Object? videoFileName = ignore, Object? videoFileName = ignore,
Object? trickPlayModel = ignore, Object? trickPlayModel = ignore,
Object? introOutroSkipModel = ignore, Object? mediaSegments = ignore,
Object? images = ignore, Object? images = ignore,
Object? userData = ignore, Object? userData = ignore,
}) { }) {
@ -510,7 +510,7 @@ class _ISyncedItemQueryUpdateImpl implements _ISyncedItemQueryUpdate {
if (fileSize != ignore) 7: fileSize as int?, if (fileSize != ignore) 7: fileSize as int?,
if (videoFileName != ignore) 8: videoFileName as String?, if (videoFileName != ignore) 8: videoFileName as String?,
if (trickPlayModel != ignore) 9: trickPlayModel as String?, if (trickPlayModel != ignore) 9: trickPlayModel as String?,
if (introOutroSkipModel != ignore) 10: introOutroSkipModel as String?, if (mediaSegments != ignore) 10: mediaSegments as String?,
if (images != ignore) 11: images as String?, if (images != ignore) 11: images as String?,
if (userData != ignore) 14: userData as String?, if (userData != ignore) 14: userData as String?,
}); });
@ -540,7 +540,7 @@ class _ISyncedItemQueryBuilderUpdateImpl implements _ISyncedItemQueryUpdate {
Object? fileSize = ignore, Object? fileSize = ignore,
Object? videoFileName = ignore, Object? videoFileName = ignore,
Object? trickPlayModel = ignore, Object? trickPlayModel = ignore,
Object? introOutroSkipModel = ignore, Object? mediaSegments = ignore,
Object? images = ignore, Object? images = ignore,
Object? userData = ignore, Object? userData = ignore,
}) { }) {
@ -555,7 +555,7 @@ class _ISyncedItemQueryBuilderUpdateImpl implements _ISyncedItemQueryUpdate {
if (fileSize != ignore) 7: fileSize as int?, if (fileSize != ignore) 7: fileSize as int?,
if (videoFileName != ignore) 8: videoFileName as String?, if (videoFileName != ignore) 8: videoFileName as String?,
if (trickPlayModel != ignore) 9: trickPlayModel as String?, if (trickPlayModel != ignore) 9: trickPlayModel as String?,
if (introOutroSkipModel != ignore) 10: introOutroSkipModel as String?, if (mediaSegments != ignore) 10: mediaSegments as String?,
if (images != ignore) 11: images as String?, if (images != ignore) 11: images as String?,
if (userData != ignore) 14: userData as String?, if (userData != ignore) 14: userData as String?,
}); });
@ -2015,21 +2015,21 @@ extension ISyncedItemQueryFilter
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelIsNull() { mediaSegmentsIsNull() {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const IsNullCondition(property: 10)); return query.addFilterCondition(const IsNullCondition(property: 10));
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelIsNotNull() { mediaSegmentsIsNotNull() {
return QueryBuilder.apply(not(), (query) { return QueryBuilder.apply(not(), (query) {
return query.addFilterCondition(const IsNullCondition(property: 10)); return query.addFilterCondition(const IsNullCondition(property: 10));
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelEqualTo( mediaSegmentsEqualTo(
String? value, { String? value, {
bool caseSensitive = true, bool caseSensitive = true,
}) { }) {
@ -2045,7 +2045,7 @@ extension ISyncedItemQueryFilter
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelGreaterThan( mediaSegmentsGreaterThan(
String? value, { String? value, {
bool caseSensitive = true, bool caseSensitive = true,
}) { }) {
@ -2061,7 +2061,7 @@ extension ISyncedItemQueryFilter
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelGreaterThanOrEqualTo( mediaSegmentsGreaterThanOrEqualTo(
String? value, { String? value, {
bool caseSensitive = true, bool caseSensitive = true,
}) { }) {
@ -2077,7 +2077,7 @@ extension ISyncedItemQueryFilter
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelLessThan( mediaSegmentsLessThan(
String? value, { String? value, {
bool caseSensitive = true, bool caseSensitive = true,
}) { }) {
@ -2093,7 +2093,7 @@ extension ISyncedItemQueryFilter
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelLessThanOrEqualTo( mediaSegmentsLessThanOrEqualTo(
String? value, { String? value, {
bool caseSensitive = true, bool caseSensitive = true,
}) { }) {
@ -2109,7 +2109,7 @@ extension ISyncedItemQueryFilter
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelBetween( mediaSegmentsBetween(
String? lower, String? lower,
String? upper, { String? upper, {
bool caseSensitive = true, bool caseSensitive = true,
@ -2127,7 +2127,7 @@ extension ISyncedItemQueryFilter
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelStartsWith( mediaSegmentsStartsWith(
String value, { String value, {
bool caseSensitive = true, bool caseSensitive = true,
}) { }) {
@ -2143,7 +2143,7 @@ extension ISyncedItemQueryFilter
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelEndsWith( mediaSegmentsEndsWith(
String value, { String value, {
bool caseSensitive = true, bool caseSensitive = true,
}) { }) {
@ -2159,7 +2159,7 @@ extension ISyncedItemQueryFilter
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelContains(String value, {bool caseSensitive = true}) { mediaSegmentsContains(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addFilterCondition( return query.addFilterCondition(
ContainsCondition( ContainsCondition(
@ -2172,7 +2172,7 @@ extension ISyncedItemQueryFilter
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelMatches(String pattern, {bool caseSensitive = true}) { mediaSegmentsMatches(String pattern, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addFilterCondition( return query.addFilterCondition(
MatchesCondition( MatchesCondition(
@ -2185,7 +2185,7 @@ extension ISyncedItemQueryFilter
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelIsEmpty() { mediaSegmentsIsEmpty() {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addFilterCondition( return query.addFilterCondition(
const EqualCondition( const EqualCondition(
@ -2197,7 +2197,7 @@ extension ISyncedItemQueryFilter
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition> QueryBuilder<ISyncedItem, ISyncedItem, QAfterFilterCondition>
introOutroSkipModelIsNotEmpty() { mediaSegmentsIsNotEmpty() {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addFilterCondition( return query.addFilterCondition(
const GreaterCondition( const GreaterCondition(
@ -3189,8 +3189,8 @@ extension ISyncedItemQuerySortBy
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> sortByMediaSegments(
sortByIntroOutroSkipModel({bool caseSensitive = true}) { {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addSortBy( return query.addSortBy(
10, 10,
@ -3199,8 +3199,8 @@ extension ISyncedItemQuerySortBy
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> sortByMediaSegmentsDesc(
sortByIntroOutroSkipModelDesc({bool caseSensitive = true}) { {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addSortBy( return query.addSortBy(
10, 10,
@ -3377,15 +3377,15 @@ extension ISyncedItemQuerySortThenBy
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> thenByMediaSegments(
thenByIntroOutroSkipModel({bool caseSensitive = true}) { {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addSortBy(10, caseSensitive: caseSensitive); return query.addSortBy(10, caseSensitive: caseSensitive);
}); });
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> QueryBuilder<ISyncedItem, ISyncedItem, QAfterSortBy> thenByMediaSegmentsDesc(
thenByIntroOutroSkipModelDesc({bool caseSensitive = true}) { {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addSortBy(10, sort: Sort.desc, caseSensitive: caseSensitive); return query.addSortBy(10, sort: Sort.desc, caseSensitive: caseSensitive);
}); });
@ -3477,7 +3477,7 @@ extension ISyncedItemQueryWhereDistinct
} }
QueryBuilder<ISyncedItem, ISyncedItem, QAfterDistinct> QueryBuilder<ISyncedItem, ISyncedItem, QAfterDistinct>
distinctByIntroOutroSkipModel({bool caseSensitive = true}) { distinctByMediaSegments({bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(10, caseSensitive: caseSensitive); return query.addDistinctBy(10, caseSensitive: caseSensitive);
}); });
@ -3566,8 +3566,7 @@ extension ISyncedItemQueryProperty1
}); });
} }
QueryBuilder<ISyncedItem, String?, QAfterProperty> QueryBuilder<ISyncedItem, String?, QAfterProperty> mediaSegmentsProperty() {
introOutroSkipModelProperty() {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addProperty(10); return query.addProperty(10);
}); });
@ -3657,7 +3656,7 @@ extension ISyncedItemQueryProperty2<R>
} }
QueryBuilder<ISyncedItem, (R, String?), QAfterProperty> QueryBuilder<ISyncedItem, (R, String?), QAfterProperty>
introOutroSkipModelProperty() { mediaSegmentsProperty() {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addProperty(10); return query.addProperty(10);
}); });
@ -3749,7 +3748,7 @@ extension ISyncedItemQueryProperty3<R1, R2>
} }
QueryBuilder<ISyncedItem, (R1, R2, String?), QOperations> QueryBuilder<ISyncedItem, (R1, R2, String?), QOperations>
introOutroSkipModelProperty() { mediaSegmentsProperty() {
return QueryBuilder.apply(this, (query) { return QueryBuilder.apply(this, (query) {
return query.addProperty(10); return query.addProperty(10);
}); });

View file

@ -13,7 +13,7 @@ import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/items/chapters_model.dart'; import 'package:fladder/models/items/chapters_model.dart';
import 'package:fladder/models/items/images_models.dart'; import 'package:fladder/models/items/images_models.dart';
import 'package:fladder/models/items/intro_skip_model.dart'; import 'package:fladder/models/items/media_segments_model.dart';
import 'package:fladder/models/items/item_shared_models.dart'; import 'package:fladder/models/items/item_shared_models.dart';
import 'package:fladder/models/items/media_streams_model.dart'; import 'package:fladder/models/items/media_streams_model.dart';
import 'package:fladder/models/items/trick_play_model.dart'; import 'package:fladder/models/items/trick_play_model.dart';
@ -38,7 +38,7 @@ class SyncedItem with _$SyncedItem {
String? sortName, String? sortName,
int? fileSize, int? fileSize,
String? videoFileName, String? videoFileName,
IntroOutSkipModel? introOutSkipModel, MediaSegmentsModel? mediaSegments,
TrickPlayModel? fTrickPlayModel, TrickPlayModel? fTrickPlayModel,
ImagesData? fImages, ImagesData? fImages,
@Default([]) List<Chapter> fChapters, @Default([]) List<Chapter> fChapters,
@ -132,8 +132,8 @@ class SyncedItem with _$SyncedItem {
path: joinAll([savePath, isarSyncedItem.path ?? ""]), path: joinAll([savePath, isarSyncedItem.path ?? ""]),
fileSize: isarSyncedItem.fileSize, fileSize: isarSyncedItem.fileSize,
videoFileName: isarSyncedItem.videoFileName, videoFileName: isarSyncedItem.videoFileName,
introOutSkipModel: isarSyncedItem.introOutroSkipModel != null mediaSegments: isarSyncedItem.mediaSegments != null
? IntroOutSkipModel.fromJson(jsonDecode(isarSyncedItem.introOutroSkipModel!)) ? MediaSegmentsModel.fromJson(jsonDecode(isarSyncedItem.mediaSegments!))
: null, : null,
fTrickPlayModel: isarSyncedItem.trickPlayModel != null fTrickPlayModel: isarSyncedItem.trickPlayModel != null
? TrickPlayModel.fromJson(jsonDecode(isarSyncedItem.trickPlayModel!)) ? TrickPlayModel.fromJson(jsonDecode(isarSyncedItem.trickPlayModel!))

View file

@ -25,8 +25,7 @@ mixin _$SyncedItem {
String? get sortName => throw _privateConstructorUsedError; String? get sortName => throw _privateConstructorUsedError;
int? get fileSize => throw _privateConstructorUsedError; int? get fileSize => throw _privateConstructorUsedError;
String? get videoFileName => throw _privateConstructorUsedError; String? get videoFileName => throw _privateConstructorUsedError;
IntroOutSkipModel? get introOutSkipModel => MediaSegmentsModel? get mediaSegments => throw _privateConstructorUsedError;
throw _privateConstructorUsedError;
TrickPlayModel? get fTrickPlayModel => throw _privateConstructorUsedError; TrickPlayModel? get fTrickPlayModel => throw _privateConstructorUsedError;
ImagesData? get fImages => throw _privateConstructorUsedError; ImagesData? get fImages => throw _privateConstructorUsedError;
List<Chapter> get fChapters => throw _privateConstructorUsedError; List<Chapter> get fChapters => throw _privateConstructorUsedError;
@ -57,14 +56,14 @@ abstract class $SyncedItemCopyWith<$Res> {
String? sortName, String? sortName,
int? fileSize, int? fileSize,
String? videoFileName, String? videoFileName,
IntroOutSkipModel? introOutSkipModel, MediaSegmentsModel? mediaSegments,
TrickPlayModel? fTrickPlayModel, TrickPlayModel? fTrickPlayModel,
ImagesData? fImages, ImagesData? fImages,
List<Chapter> fChapters, List<Chapter> fChapters,
List<SubStreamModel> subtitles, List<SubStreamModel> subtitles,
@UserDataJsonSerializer() UserData? userData}); @UserDataJsonSerializer() UserData? userData});
$IntroOutSkipModelCopyWith<$Res>? get introOutSkipModel; $MediaSegmentsModelCopyWith<$Res>? get mediaSegments;
$TrickPlayModelCopyWith<$Res>? get fTrickPlayModel; $TrickPlayModelCopyWith<$Res>? get fTrickPlayModel;
} }
@ -92,7 +91,7 @@ class _$SyncedItemCopyWithImpl<$Res, $Val extends SyncedItem>
Object? sortName = freezed, Object? sortName = freezed,
Object? fileSize = freezed, Object? fileSize = freezed,
Object? videoFileName = freezed, Object? videoFileName = freezed,
Object? introOutSkipModel = freezed, Object? mediaSegments = freezed,
Object? fTrickPlayModel = freezed, Object? fTrickPlayModel = freezed,
Object? fImages = freezed, Object? fImages = freezed,
Object? fChapters = null, Object? fChapters = null,
@ -136,10 +135,10 @@ class _$SyncedItemCopyWithImpl<$Res, $Val extends SyncedItem>
? _value.videoFileName ? _value.videoFileName
: videoFileName // ignore: cast_nullable_to_non_nullable : videoFileName // ignore: cast_nullable_to_non_nullable
as String?, as String?,
introOutSkipModel: freezed == introOutSkipModel mediaSegments: freezed == mediaSegments
? _value.introOutSkipModel ? _value.mediaSegments
: introOutSkipModel // ignore: cast_nullable_to_non_nullable : mediaSegments // ignore: cast_nullable_to_non_nullable
as IntroOutSkipModel?, as MediaSegmentsModel?,
fTrickPlayModel: freezed == fTrickPlayModel fTrickPlayModel: freezed == fTrickPlayModel
? _value.fTrickPlayModel ? _value.fTrickPlayModel
: fTrickPlayModel // ignore: cast_nullable_to_non_nullable : fTrickPlayModel // ignore: cast_nullable_to_non_nullable
@ -167,13 +166,13 @@ class _$SyncedItemCopyWithImpl<$Res, $Val extends SyncedItem>
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@override @override
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
$IntroOutSkipModelCopyWith<$Res>? get introOutSkipModel { $MediaSegmentsModelCopyWith<$Res>? get mediaSegments {
if (_value.introOutSkipModel == null) { if (_value.mediaSegments == null) {
return null; return null;
} }
return $IntroOutSkipModelCopyWith<$Res>(_value.introOutSkipModel!, (value) { return $MediaSegmentsModelCopyWith<$Res>(_value.mediaSegments!, (value) {
return _then(_value.copyWith(introOutSkipModel: value) as $Val); return _then(_value.copyWith(mediaSegments: value) as $Val);
}); });
} }
@ -210,7 +209,7 @@ abstract class _$$SyncItemImplCopyWith<$Res>
String? sortName, String? sortName,
int? fileSize, int? fileSize,
String? videoFileName, String? videoFileName,
IntroOutSkipModel? introOutSkipModel, MediaSegmentsModel? mediaSegments,
TrickPlayModel? fTrickPlayModel, TrickPlayModel? fTrickPlayModel,
ImagesData? fImages, ImagesData? fImages,
List<Chapter> fChapters, List<Chapter> fChapters,
@ -218,7 +217,7 @@ abstract class _$$SyncItemImplCopyWith<$Res>
@UserDataJsonSerializer() UserData? userData}); @UserDataJsonSerializer() UserData? userData});
@override @override
$IntroOutSkipModelCopyWith<$Res>? get introOutSkipModel; $MediaSegmentsModelCopyWith<$Res>? get mediaSegments;
@override @override
$TrickPlayModelCopyWith<$Res>? get fTrickPlayModel; $TrickPlayModelCopyWith<$Res>? get fTrickPlayModel;
} }
@ -245,7 +244,7 @@ class __$$SyncItemImplCopyWithImpl<$Res>
Object? sortName = freezed, Object? sortName = freezed,
Object? fileSize = freezed, Object? fileSize = freezed,
Object? videoFileName = freezed, Object? videoFileName = freezed,
Object? introOutSkipModel = freezed, Object? mediaSegments = freezed,
Object? fTrickPlayModel = freezed, Object? fTrickPlayModel = freezed,
Object? fImages = freezed, Object? fImages = freezed,
Object? fChapters = null, Object? fChapters = null,
@ -289,10 +288,10 @@ class __$$SyncItemImplCopyWithImpl<$Res>
? _value.videoFileName ? _value.videoFileName
: videoFileName // ignore: cast_nullable_to_non_nullable : videoFileName // ignore: cast_nullable_to_non_nullable
as String?, as String?,
introOutSkipModel: freezed == introOutSkipModel mediaSegments: freezed == mediaSegments
? _value.introOutSkipModel ? _value.mediaSegments
: introOutSkipModel // ignore: cast_nullable_to_non_nullable : mediaSegments // ignore: cast_nullable_to_non_nullable
as IntroOutSkipModel?, as MediaSegmentsModel?,
fTrickPlayModel: freezed == fTrickPlayModel fTrickPlayModel: freezed == fTrickPlayModel
? _value.fTrickPlayModel ? _value.fTrickPlayModel
: fTrickPlayModel // ignore: cast_nullable_to_non_nullable : fTrickPlayModel // ignore: cast_nullable_to_non_nullable
@ -330,7 +329,7 @@ class _$SyncItemImpl extends _SyncItem {
this.sortName, this.sortName,
this.fileSize, this.fileSize,
this.videoFileName, this.videoFileName,
this.introOutSkipModel, this.mediaSegments,
this.fTrickPlayModel, this.fTrickPlayModel,
this.fImages, this.fImages,
final List<Chapter> fChapters = const [], final List<Chapter> fChapters = const [],
@ -361,7 +360,7 @@ class _$SyncItemImpl extends _SyncItem {
@override @override
final String? videoFileName; final String? videoFileName;
@override @override
final IntroOutSkipModel? introOutSkipModel; final MediaSegmentsModel? mediaSegments;
@override @override
final TrickPlayModel? fTrickPlayModel; final TrickPlayModel? fTrickPlayModel;
@override @override
@ -390,7 +389,7 @@ class _$SyncItemImpl extends _SyncItem {
@override @override
String toString() { String toString() {
return 'SyncedItem(id: $id, syncing: $syncing, parentId: $parentId, userId: $userId, path: $path, markedForDelete: $markedForDelete, sortName: $sortName, fileSize: $fileSize, videoFileName: $videoFileName, introOutSkipModel: $introOutSkipModel, fTrickPlayModel: $fTrickPlayModel, fImages: $fImages, fChapters: $fChapters, subtitles: $subtitles, userData: $userData)'; return 'SyncedItem(id: $id, syncing: $syncing, parentId: $parentId, userId: $userId, path: $path, markedForDelete: $markedForDelete, sortName: $sortName, fileSize: $fileSize, videoFileName: $videoFileName, mediaSegments: $mediaSegments, fTrickPlayModel: $fTrickPlayModel, fImages: $fImages, fChapters: $fChapters, subtitles: $subtitles, userData: $userData)';
} }
@override @override
@ -412,8 +411,8 @@ class _$SyncItemImpl extends _SyncItem {
other.fileSize == fileSize) && other.fileSize == fileSize) &&
(identical(other.videoFileName, videoFileName) || (identical(other.videoFileName, videoFileName) ||
other.videoFileName == videoFileName) && other.videoFileName == videoFileName) &&
(identical(other.introOutSkipModel, introOutSkipModel) || (identical(other.mediaSegments, mediaSegments) ||
other.introOutSkipModel == introOutSkipModel) && other.mediaSegments == mediaSegments) &&
(identical(other.fTrickPlayModel, fTrickPlayModel) || (identical(other.fTrickPlayModel, fTrickPlayModel) ||
other.fTrickPlayModel == fTrickPlayModel) && other.fTrickPlayModel == fTrickPlayModel) &&
(identical(other.fImages, fImages) || other.fImages == fImages) && (identical(other.fImages, fImages) || other.fImages == fImages) &&
@ -437,7 +436,7 @@ class _$SyncItemImpl extends _SyncItem {
sortName, sortName,
fileSize, fileSize,
videoFileName, videoFileName,
introOutSkipModel, mediaSegments,
fTrickPlayModel, fTrickPlayModel,
fImages, fImages,
const DeepCollectionEquality().hash(_fChapters), const DeepCollectionEquality().hash(_fChapters),
@ -464,7 +463,7 @@ abstract class _SyncItem extends SyncedItem {
final String? sortName, final String? sortName,
final int? fileSize, final int? fileSize,
final String? videoFileName, final String? videoFileName,
final IntroOutSkipModel? introOutSkipModel, final MediaSegmentsModel? mediaSegments,
final TrickPlayModel? fTrickPlayModel, final TrickPlayModel? fTrickPlayModel,
final ImagesData? fImages, final ImagesData? fImages,
final List<Chapter> fChapters, final List<Chapter> fChapters,
@ -491,7 +490,7 @@ abstract class _SyncItem extends SyncedItem {
@override @override
String? get videoFileName; String? get videoFileName;
@override @override
IntroOutSkipModel? get introOutSkipModel; MediaSegmentsModel? get mediaSegments;
@override @override
TrickPlayModel? get fTrickPlayModel; TrickPlayModel? get fTrickPlayModel;
@override @override

View file

@ -1,16 +1,17 @@
import 'package:flutter/material.dart';
// ignore_for_file: public_member_api_docs, sort_constructors_first // ignore_for_file: public_member_api_docs, sort_constructors_first
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:ficonsax/ficonsax.dart'; import 'package:ficonsax/ficonsax.dart';
import 'package:fladder/models/items/item_stream_model.dart';
import 'package:fladder/models/syncing/sync_item.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:media_kit/media_kit.dart'; import 'package:media_kit/media_kit.dart';
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart'; import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
import 'package:fladder/models/items/chapters_model.dart'; import 'package:fladder/models/items/chapters_model.dart';
import 'package:fladder/models/items/intro_skip_model.dart'; import 'package:fladder/models/items/item_stream_model.dart';
import 'package:fladder/models/items/media_segments_model.dart';
import 'package:fladder/models/items/media_streams_model.dart'; import 'package:fladder/models/items/media_streams_model.dart';
import 'package:fladder/models/syncing/sync_item.dart';
import 'package:fladder/providers/user_provider.dart'; import 'package:fladder/providers/user_provider.dart';
enum PlaybackType { enum PlaybackType {
@ -100,7 +101,7 @@ class VideoStream {
final String playSessionId; final String playSessionId;
final List<Chapter>? chapters; final List<Chapter>? chapters;
final List<Chapter>? trickPlay; final List<Chapter>? trickPlay;
final IntroSkipModel? introSkipModel; final MediaSegmentsModel? mediaSegments;
final int? audioStreamIndex; final int? audioStreamIndex;
final int? subtitleStreamIndex; final int? subtitleStreamIndex;
final MediaStreamsModel? mediaStreamsModel; final MediaStreamsModel? mediaStreamsModel;
@ -129,7 +130,7 @@ class VideoStream {
required this.playSessionId, required this.playSessionId,
this.chapters, this.chapters,
this.trickPlay, this.trickPlay,
this.introSkipModel, this.mediaSegments,
this.audioStreamIndex, this.audioStreamIndex,
this.subtitleStreamIndex, this.subtitleStreamIndex,
this.mediaStreamsModel, this.mediaStreamsModel,
@ -143,7 +144,7 @@ class VideoStream {
String? playSessionId, String? playSessionId,
List<Chapter>? chapters, List<Chapter>? chapters,
List<Chapter>? trickPlay, List<Chapter>? trickPlay,
IntroSkipModel? introSkipModel, MediaSegmentsModel? mediaSegments,
int? audioStreamIndex, int? audioStreamIndex,
int? subtitleStreamIndex, int? subtitleStreamIndex,
MediaStreamsModel? mediaStreamsModel, MediaStreamsModel? mediaStreamsModel,
@ -156,7 +157,7 @@ class VideoStream {
playSessionId: playSessionId ?? this.playSessionId, playSessionId: playSessionId ?? this.playSessionId,
chapters: chapters ?? this.chapters, chapters: chapters ?? this.chapters,
trickPlay: trickPlay ?? this.trickPlay, trickPlay: trickPlay ?? this.trickPlay,
introSkipModel: introSkipModel ?? this.introSkipModel, mediaSegments: mediaSegments ?? this.mediaSegments,
audioStreamIndex: audioStreamIndex ?? this.audioStreamIndex, audioStreamIndex: audioStreamIndex ?? this.audioStreamIndex,
subtitleStreamIndex: subtitleStreamIndex ?? this.subtitleStreamIndex, subtitleStreamIndex: subtitleStreamIndex ?? this.subtitleStreamIndex,
mediaStreamsModel: mediaStreamsModel ?? this.mediaStreamsModel, mediaStreamsModel: mediaStreamsModel ?? this.mediaStreamsModel,

View file

@ -1,4 +1,3 @@
import 'dart:convert';
import 'dart:developer'; import 'dart:developer';
import 'dart:typed_data'; import 'dart:typed_data';
@ -12,7 +11,7 @@ import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
import 'package:fladder/models/account_model.dart'; import 'package:fladder/models/account_model.dart';
import 'package:fladder/models/credentials_model.dart'; import 'package:fladder/models/credentials_model.dart';
import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/items/intro_skip_model.dart'; import 'package:fladder/models/items/media_segments_model.dart';
import 'package:fladder/models/items/trick_play_model.dart'; import 'package:fladder/models/items/trick_play_model.dart';
import 'package:fladder/providers/api_provider.dart'; import 'package:fladder/providers/api_provider.dart';
import 'package:fladder/providers/image_provider.dart'; import 'package:fladder/providers/image_provider.dart';
@ -871,20 +870,14 @@ class JellyService {
userId: account?.id, userId: account?.id,
); );
Future<Response<IntroOutSkipModel>?> introSkipGet({ Future<Response<MediaSegmentsModel>?> mediaSegmentsGet({
required String id, required String id,
}) async { }) async {
try { try {
final response = await api.episodeIdIntroTimestampsGet(id: id); final response = await api.mediaSegmentsItemIdGet(itemId: id);
final outro = await api.episodeIdIntroSkipperSegmentsGet(id: id); final newSegments = response.body?.items?.map((e) => e.toSegment).toList() ?? [];
final map = jsonDecode(outro.bodyString) as Map<String, dynamic>;
final newModel = IntroOutSkipModel(
intro:
map["Introduction"] != null ? IntroSkipModel.fromJson(map["Introduction"] as Map<String, dynamic>) : null,
credits: map["Credits"] != null ? IntroSkipModel.fromJson(map["Credits"] as Map<String, dynamic>) : null,
);
return response.copyWith( return response.copyWith(
body: newModel, body: MediaSegmentsModel(segments: newSegments),
); );
} catch (e) { } catch (e) {
log(e.toString()); log(e.toString());
@ -927,7 +920,7 @@ class JellyService {
} }
} }
Future<Response<List<SessionInfo>>> sessionsInfo(String deviceId) async => api.sessionsGet(deviceId: deviceId); Future<Response<List<SessionInfoDto>>> sessionsInfo(String deviceId) async => api.sessionsGet(deviceId: deviceId);
Future<Response<bool>> quickConnect(String code) async => api.quickConnectAuthorizePost(code: code); Future<Response<bool>> quickConnect(String code) async => api.quickConnectAuthorizePost(code: code);

View file

@ -436,12 +436,12 @@ class SyncNotifier extends StateNotifier<SyncSettingsModel> {
final subtitles = await saveExternalSubtitles(newState?.mediaStreamsModel?.subStreams, syncItem); final subtitles = await saveExternalSubtitles(newState?.mediaStreamsModel?.subStreams, syncItem);
final trickPlayFile = await saveTrickPlayData(item, directory); final trickPlayFile = await saveTrickPlayData(item, directory);
final introOutroSkip = (await api.introSkipGet(id: syncItem.id))?.body; final mediaSegments = (await api.mediaSegmentsGet(id: syncItem.id))?.body;
syncItem = syncItem.copyWith( syncItem = syncItem.copyWith(
subtitles: subtitles, subtitles: subtitles,
fTrickPlayModel: trickPlayFile, fTrickPlayModel: trickPlayFile,
introOutSkipModel: introOutroSkip, mediaSegments: mediaSegments,
); );
await updateItem(syncItem); await updateItem(syncItem);

View file

@ -1,9 +1,9 @@
import 'package:fladder/providers/video_player_provider.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:media_kit/media_kit.dart'; import 'package:media_kit/media_kit.dart';
import 'package:fladder/providers/video_player_provider.dart';
import 'package:fladder/screens/video_player/components/video_player_chapters.dart'; import 'package:fladder/screens/video_player/components/video_player_chapters.dart';
import 'package:fladder/screens/video_player/components/video_player_queue.dart'; import 'package:fladder/screens/video_player/components/video_player_queue.dart';
@ -84,10 +84,10 @@ class IntroSkipButton extends ConsumerWidget {
} }
} }
class CreditsSkipButton extends ConsumerWidget { class OutroSkipButton extends ConsumerWidget {
final bool isOverlayVisible; final bool isOverlayVisible;
final Function()? skipCredits; final Function()? skipOutro;
const CreditsSkipButton({this.skipCredits, required this.isOverlayVisible, super.key}); const OutroSkipButton({this.skipOutro, required this.isOverlayVisible, super.key});
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
@ -96,7 +96,7 @@ class CreditsSkipButton extends ConsumerWidget {
opacity: 1, opacity: 1,
duration: const Duration(milliseconds: 250), duration: const Duration(milliseconds: 250),
child: ElevatedButton( child: ElevatedButton(
onPressed: () => skipCredits?.call(), onPressed: () => skipOutro?.call(),
style: ElevatedButton.styleFrom(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5))), style: ElevatedButton.styleFrom(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5))),
child: const Padding( child: const Padding(
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),

View file

@ -81,7 +81,7 @@ class _VideoPlayerNextWrapperState extends ConsumerState<VideoPlayerNextWrapper>
return; return;
} }
final credits = ref.read(playBackModel)?.introSkipModel?.credits; final credits = ref.read(playBackModel)?.mediaSegments?.outro;
if (nextType == AutoNextType.static || credits == null) { if (nextType == AutoNextType.static || credits == null) {
if ((model.duration - model.position).abs() < const Duration(seconds: 32)) { if ((model.duration - model.position).abs() < const Duration(seconds: 32)) {

View file

@ -6,7 +6,7 @@ import 'package:collection/collection.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/models/items/chapters_model.dart'; import 'package:fladder/models/items/chapters_model.dart';
import 'package:fladder/models/items/intro_skip_model.dart'; import 'package:fladder/models/items/media_segments_model.dart';
import 'package:fladder/providers/video_player_provider.dart'; import 'package:fladder/providers/video_player_provider.dart';
import 'package:fladder/util/duration_extensions.dart'; import 'package:fladder/util/duration_extensions.dart';
import 'package:fladder/util/list_padding.dart'; import 'package:fladder/util/list_padding.dart';
@ -54,7 +54,7 @@ class _ChapterProgressSliderState extends ConsumerState<VideoProgressBar> {
final isVisible = (onDragStart ? true : onHoverStart); final isVisible = (onDragStart ? true : onHoverStart);
final player = ref.watch(videoPlayerProvider); final player = ref.watch(videoPlayerProvider);
final position = onDragStart ? currentDuration : widget.position; final position = onDragStart ? currentDuration : widget.position;
final IntroOutSkipModel? introCreditsModel = ref.read(playBackModel.select((value) => value?.introSkipModel)); final MediaSegmentsModel? mediaSegments = ref.read(playBackModel.select((value) => value?.mediaSegments));
final relativeFraction = position.inMilliseconds / widget.duration.inMilliseconds; final relativeFraction = position.inMilliseconds / widget.duration.inMilliseconds;
return LayoutBuilder( return LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
@ -138,36 +138,22 @@ class _ChapterProgressSliderState extends ConsumerState<VideoProgressBar> {
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
if (introCreditsModel?.intro?.start != null && introCreditsModel?.intro?.end != null) ...?mediaSegments?.segments.map(
Positioned( (segment) => Positioned(
left: calculateStartOffset(constraints, introCreditsModel!.intro!.start), left: calculateStartOffset(constraints, segment.start),
right: calculateRightOffset(constraints, introCreditsModel.intro!.end), right: calculateRightOffset(constraints, segment.end),
bottom: 0, bottom: 0,
child: Container( child: Container(
height: 6, height: 6,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.greenAccent.withOpacity(0.8), color: segment.type.color,
borderRadius: BorderRadius.circular(
100,
),
),
),
),
if (introCreditsModel?.credits?.start != null && introCreditsModel?.credits?.end != null)
Positioned(
left: calculateStartOffset(constraints, introCreditsModel!.credits!.start),
right: calculateRightOffset(constraints, introCreditsModel.credits!.end),
bottom: 0,
child: Container(
height: 6,
decoration: BoxDecoration(
color: Colors.orangeAccent.withOpacity(0.8),
borderRadius: BorderRadius.circular( borderRadius: BorderRadius.circular(
100, 100,
), ),
), ),
), ),
), ),
),
if (!widget.buffering) ...{ if (!widget.buffering) ...{
//VideoBufferBar //VideoBufferBar
Positioned( Positioned(

View file

@ -13,7 +13,7 @@ import 'package:screen_brightness/screen_brightness.dart';
import 'package:universal_html/html.dart' as html; import 'package:universal_html/html.dart' as html;
import 'package:window_manager/window_manager.dart'; import 'package:window_manager/window_manager.dart';
import 'package:fladder/models/items/intro_skip_model.dart'; import 'package:fladder/models/items/media_segments_model.dart';
import 'package:fladder/models/media_playback_model.dart'; import 'package:fladder/models/media_playback_model.dart';
import 'package:fladder/models/playback/playback_model.dart'; import 'package:fladder/models/playback/playback_model.dart';
import 'package:fladder/providers/settings/client_settings_provider.dart'; import 'package:fladder/providers/settings/client_settings_provider.dart';
@ -57,10 +57,10 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
late final double bottomPadding = MediaQuery.of(context).viewPadding.bottom; late final double bottomPadding = MediaQuery.of(context).viewPadding.bottom;
bool _onKey(KeyEvent value) { bool _onKey(KeyEvent value) {
final introSkipModel = ref.read(playBackModel.select((value) => value?.introSkipModel)); final mediaSegments = ref.read(playBackModel.select((value) => value?.mediaSegments));
final position = ref.read(mediaPlaybackProvider).position; final position = ref.read(mediaPlaybackProvider).position;
bool showIntroSkipButton = introSkipModel?.introInRange(position) ?? false; bool showIntroSkipButton = mediaSegments?.intro?.inRange(position) ?? false;
bool showCreditSkipButton = introSkipModel?.creditsInRange(position) ?? false; bool showOutroSkipButton = mediaSegments?.outro?.inRange(position) ?? false;
if (value is KeyRepeatEvent) { if (value is KeyRepeatEvent) {
if (value.logicalKey == LogicalKeyboardKey.arrowUp) { if (value.logicalKey == LogicalKeyboardKey.arrowUp) {
resetTimer(); resetTimer();
@ -76,9 +76,9 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
if (value is KeyDownEvent) { if (value is KeyDownEvent) {
if (value.logicalKey == LogicalKeyboardKey.keyS) { if (value.logicalKey == LogicalKeyboardKey.keyS) {
if (showIntroSkipButton) { if (showIntroSkipButton) {
skipIntro(introSkipModel); skipIntro(mediaSegments);
} else if (showCreditSkipButton) { } else if (showOutroSkipButton) {
skipCredits(introSkipModel); skipOutro(mediaSegments);
} }
return true; return true;
} }
@ -116,7 +116,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final introSkipModel = ref.watch(playBackModel.select((value) => value?.introSkipModel)); final mediaSegments = ref.watch(playBackModel.select((value) => value?.mediaSegments));
final player = ref.watch(videoPlayerProvider.select((value) => value.controller)); final player = ref.watch(videoPlayerProvider.select((value) => value.controller));
return InputHandler( return InputHandler(
autoFocus: false, autoFocus: false,
@ -167,8 +167,8 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
Consumer( Consumer(
builder: (context, ref, child) { builder: (context, ref, child) {
final position = ref.watch(mediaPlaybackProvider.select((value) => value.position)); final position = ref.watch(mediaPlaybackProvider.select((value) => value.position));
bool showIntroSkipButton = introSkipModel?.introInRange(position) ?? false; bool showIntroSkipButton = mediaSegments?.intro?.inRange(position) ?? false;
bool showCreditSkipButton = introSkipModel?.creditsInRange(position) ?? false; bool showOutroSkipButton = mediaSegments?.outro?.inRange(position) ?? false;
return Stack( return Stack(
children: [ children: [
if (showIntroSkipButton) if (showIntroSkipButton)
@ -178,18 +178,18 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
padding: const EdgeInsets.all(32), padding: const EdgeInsets.all(32),
child: IntroSkipButton( child: IntroSkipButton(
isOverlayVisible: showOverlay, isOverlayVisible: showOverlay,
skipIntro: () => skipIntro(introSkipModel), skipIntro: () => skipIntro(mediaSegments),
), ),
), ),
), ),
if (showCreditSkipButton) if (showOutroSkipButton)
Align( Align(
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
child: Padding( child: Padding(
padding: const EdgeInsets.all(32), padding: const EdgeInsets.all(32),
child: CreditsSkipButton( child: OutroSkipButton(
isOverlayVisible: showOverlay, isOverlayVisible: showOverlay,
skipCredits: () => skipCredits(introSkipModel), skipOutro: () => skipOutro(mediaSegments),
), ),
), ),
) )
@ -582,17 +582,17 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
); );
} }
void skipIntro(IntroOutSkipModel? introSkipModel) { void skipIntro(MediaSegmentsModel? mediaSegments) {
resetTimer(); resetTimer();
final end = introSkipModel?.intro?.end; final end = mediaSegments?.intro?.end;
if (end != null) { if (end != null) {
ref.read(videoPlayerProvider).seek(end); ref.read(videoPlayerProvider).seek(end);
} }
} }
void skipCredits(IntroOutSkipModel? introSkipModel) { void skipOutro(MediaSegmentsModel? mediaSegments) {
resetTimer(); resetTimer();
final end = introSkipModel?.credits?.end; final end = mediaSegments?.outro?.end;
if (end != null) { if (end != null) {
ref.read(videoPlayerProvider).seek(end); ref.read(videoPlayerProvider).seek(end);
} }

View file

@ -6,7 +6,6 @@ import 'package:transparent_image/transparent_image.dart';
import 'package:fladder/models/items/images_models.dart'; import 'package:fladder/models/items/images_models.dart';
import 'package:fladder/providers/settings/client_settings_provider.dart'; import 'package:fladder/providers/settings/client_settings_provider.dart';
import 'package:fladder/util/adaptive_layout.dart';
class FladderImage extends ConsumerWidget { class FladderImage extends ConsumerWidget {
final ImageData? image; final ImageData? image;
@ -29,7 +28,6 @@ class FladderImage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final useBluredPlaceHolder = ref.watch(clientSettingsProvider.select((value) => value.blurPlaceHolders)); final useBluredPlaceHolder = ref.watch(clientSettingsProvider.select((value) => value.blurPlaceHolders));
final newImage = image; final newImage = image;
final blurSize = AdaptiveLayout.of(context).isDesktop ? 32 : 16;
if (newImage == null) { if (newImage == null) {
return placeHolder ?? Container(); return placeHolder ?? Container();
} else { } else {
@ -44,8 +42,6 @@ class FladderImage extends ConsumerWidget {
filterQuality: FilterQuality.low, filterQuality: FilterQuality.low,
image: BlurHashImage( image: BlurHashImage(
newImage.hash, newImage.hash,
decodingWidth: blurSize,
decodingHeight: blurSize,
), ),
), ),
if (!blurOnly) if (!blurOnly)

File diff suppressed because it is too large Load diff