mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-16 18:56:00 -07:00
feat: Improve segments visibility logic (#346)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
1a8765fbd6
commit
947da2390f
3 changed files with 30 additions and 12 deletions
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:media_kit_video/media_kit_video_controls/src/controls/extensions/duration.dart';
|
||||||
|
|
||||||
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart' as dto;
|
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart' as dto;
|
||||||
import 'package:fladder/util/localization_helper.dart';
|
import 'package:fladder/util/localization_helper.dart';
|
||||||
|
|
@ -39,7 +40,19 @@ class MediaSegment with _$MediaSegment {
|
||||||
|
|
||||||
bool inRange(Duration position) => (position.compareTo(start) >= 0 && position.compareTo(end) <= 0);
|
bool inRange(Duration position) => (position.compareTo(start) >= 0 && position.compareTo(end) <= 0);
|
||||||
|
|
||||||
bool forceShow(Duration position) => (position - start).inSeconds < (end - start).inSeconds * 0.20;
|
SegmentVisibility visibility(Duration position, {bool force = false}) {
|
||||||
|
if (force) return SegmentVisibility.visible;
|
||||||
|
var difference = (position - start);
|
||||||
|
if (difference > const Duration(minutes: 1, seconds: 30)) return SegmentVisibility.hidden;
|
||||||
|
Duration clamp = ((end - start) * 0.20).clamp(Duration.zero, const Duration(minutes: 1));
|
||||||
|
return difference < clamp ? SegmentVisibility.visible : SegmentVisibility.partially;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SegmentVisibility {
|
||||||
|
hidden,
|
||||||
|
partially,
|
||||||
|
visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Map<MediaSegmentType, SegmentSkip> defaultSegmentSkipValues = {
|
const Map<MediaSegmentType, SegmentSkip> defaultSegmentSkipValues = {
|
||||||
|
|
|
||||||
|
|
@ -66,13 +66,13 @@ class OpenQueueButton extends ConsumerWidget {
|
||||||
class SkipSegmentButton extends ConsumerWidget {
|
class SkipSegmentButton extends ConsumerWidget {
|
||||||
final MediaSegment? segment;
|
final MediaSegment? segment;
|
||||||
final SegmentSkip? skipType;
|
final SegmentSkip? skipType;
|
||||||
final bool isOverlayVisible;
|
final SegmentVisibility visibility;
|
||||||
|
|
||||||
final Function() pressedSkip;
|
final Function() pressedSkip;
|
||||||
const SkipSegmentButton({
|
const SkipSegmentButton({
|
||||||
required this.segment,
|
required this.segment,
|
||||||
this.skipType,
|
this.skipType,
|
||||||
required this.isOverlayVisible,
|
required this.visibility,
|
||||||
required this.pressedSkip,
|
required this.pressedSkip,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
@ -82,7 +82,11 @@ class SkipSegmentButton extends ConsumerWidget {
|
||||||
return AnimatedFadeSize(
|
return AnimatedFadeSize(
|
||||||
child: segment != null && skipType != SegmentSkip.none
|
child: segment != null && skipType != SegmentSkip.none
|
||||||
? AnimatedOpacity(
|
? AnimatedOpacity(
|
||||||
opacity: isOverlayVisible ? 1 : 0.15,
|
opacity: switch (visibility) {
|
||||||
|
SegmentVisibility.hidden => 0,
|
||||||
|
SegmentVisibility.partially => 0.15,
|
||||||
|
SegmentVisibility.visible => 1.0,
|
||||||
|
},
|
||||||
duration: const Duration(milliseconds: 500),
|
duration: const Duration(milliseconds: 500),
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: pressedSkip,
|
onPressed: pressedSkip,
|
||||||
|
|
|
||||||
|
|
@ -168,11 +168,13 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
||||||
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));
|
||||||
MediaSegment? segment = mediaSegments?.atPosition(position);
|
MediaSegment? segment = mediaSegments?.atPosition(position);
|
||||||
bool forceShow = segment?.forceShow(position) ?? false;
|
SegmentVisibility forceShow =
|
||||||
|
segment?.visibility(position, force: showOverlay) ?? SegmentVisibility.hidden;
|
||||||
final segmentSkipType = ref
|
final segmentSkipType = ref
|
||||||
.watch(videoPlayerSettingsProvider.select((value) => value.segmentSkipSettings[segment?.type]));
|
.watch(videoPlayerSettingsProvider.select((value) => value.segmentSkipSettings[segment?.type]));
|
||||||
final autoSkip =
|
final autoSkip = forceShow != SegmentVisibility.hidden &&
|
||||||
forceShow == true && segmentSkipType == SegmentSkip.skip && player.lastState?.buffering == false;
|
segmentSkipType == SegmentSkip.skip &&
|
||||||
|
player.lastState?.buffering == false;
|
||||||
if (autoSkip) {
|
if (autoSkip) {
|
||||||
skipToSegmentEnd(segment);
|
skipToSegmentEnd(segment);
|
||||||
}
|
}
|
||||||
|
|
@ -185,7 +187,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
||||||
child: SkipSegmentButton(
|
child: SkipSegmentButton(
|
||||||
segment: segment,
|
segment: segment,
|
||||||
skipType: segmentSkipType,
|
skipType: segmentSkipType,
|
||||||
isOverlayVisible: forceShow ? true : showOverlay,
|
visibility: forceShow,
|
||||||
pressedSkip: () => skipToSegmentEnd(segment),
|
pressedSkip: () => skipToSegmentEnd(segment),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -441,10 +443,9 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
||||||
final List<String?> details = [
|
final List<String?> details = [
|
||||||
if (AdaptiveLayout.of(context).isDesktop) item?.label(context),
|
if (AdaptiveLayout.of(context).isDesktop) item?.label(context),
|
||||||
mediaPlayback.duration.inMinutes > 1
|
mediaPlayback.duration.inMinutes > 1
|
||||||
? context.localized.endsAt(DateTime.now().add(
|
? context.localized.endsAt(DateTime.now().add(Duration(
|
||||||
Duration(milliseconds:
|
milliseconds: (mediaPlayback.duration.inMilliseconds - mediaPlayback.position.inMilliseconds) ~/
|
||||||
(mediaPlayback.duration.inMilliseconds - mediaPlayback.position.inMilliseconds) ~/ ref.read(playbackRateProvider)))
|
ref.read(playbackRateProvider))))
|
||||||
)
|
|
||||||
: null
|
: null
|
||||||
];
|
];
|
||||||
return Column(
|
return Column(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue