This commit is contained in:
kodjomoustapha 2024-02-24 01:24:35 +01:00
parent fe29eb6ecc
commit 32dbbd5e0e
9 changed files with 623 additions and 603 deletions

View file

@ -921,7 +921,17 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
), ),
Row(children: [ Row(children: [
btnToShowChapterListDialog( btnToShowChapterListDialog(
context, context.l10n.episodes, widget.episode), context,
context.l10n.episodes,
widget.episode,
onChanged: (v) {
if (v) {
_player.play();
} else {
_player.pause();
}
},
),
// IconButton( // IconButton(
// onPressed: () { // onPressed: () {
// showDialog( // showDialog(

View file

@ -8,7 +8,7 @@ class SubtitleSettingsState extends _$SubtitleSettingsState {
@override @override
PlayerSubtitleSettings build() { PlayerSubtitleSettings build() {
final subSets = isar.settings.getSync(227)!.playerSubtitleSettings; final subSets = isar.settings.getSync(227)!.playerSubtitleSettings;
if (subSets == null) { if (subSets == null || subSets.backgroundColorA == null) {
set(PlayerSubtitleSettings(), true); set(PlayerSubtitleSettings(), true);
return PlayerSubtitleSettings(); return PlayerSubtitleSettings();
} }

View file

@ -189,249 +189,254 @@ class _DesktopControllerWidgetState extends State<DesktopControllerWidget> {
const SingleActivator(LogicalKeyboardKey.escape): () => const SingleActivator(LogicalKeyboardKey.escape): () =>
setFullScreen(value: false), setFullScreen(value: false),
}, },
child: Focus( child: Stack(
autofocus: true, children: [
child: Listener( Consumer(
onPointerSignal: modifyVolumeOnScroll builder: (context, ref, _) => Positioned(
? (e) { child: CustomSubtitleView(
if (e is PointerScrollEvent) { controller: widget.videoController,
if (e.delta.dy > 0) { configuration:
final volume = SubtitleViewConfiguration(style: subtileTextStyle(ref)),
widget.videoController.player.state.volume - 5.0; )),
widget.videoController.player ),
.setVolume(volume.clamp(0.0, 100.0)); Focus(
} autofocus: true,
if (e.delta.dy < 0) { child: Listener(
final volume = onPointerSignal: modifyVolumeOnScroll
widget.videoController.player.state.volume + 5.0; ? (e) {
widget.videoController.player if (e is PointerScrollEvent) {
.setVolume(volume.clamp(0.0, 100.0)); if (e.delta.dy > 0) {
} final volume =
} widget.videoController.player.state.volume - 5.0;
} widget.videoController.player
: null, .setVolume(volume.clamp(0.0, 100.0));
child: GestureDetector( }
onTapUp: !toggleFullscreenOnDoublePress if (e.delta.dy < 0) {
? null final volume =
: (e) { widget.videoController.player.state.volume + 5.0;
final now = DateTime.now(); widget.videoController.player
final difference = now.difference(last); .setVolume(volume.clamp(0.0, 100.0));
last = now; }
if (difference < const Duration(milliseconds: 400)) {
setFullScreen();
}
},
onPanUpdate: modifyVolumeOnScroll
? (e) {
if (e.delta.dy > 0) {
final volume =
widget.videoController.player.state.volume - 5.0;
widget.videoController.player
.setVolume(volume.clamp(0.0, 100.0));
}
if (e.delta.dy < 0) {
final volume =
widget.videoController.player.state.volume + 5.0;
widget.videoController.player
.setVolume(volume.clamp(0.0, 100.0));
}
}
: null,
child: MouseRegion(
onHover: (_) => onHover(),
onEnter: (_) => onEnter(),
onExit: (_) => onExit(),
child: Stack(
children: [
Consumer(
builder: (context, ref, _) => Positioned(
child: CustomSubtitleView(
controller: widget.videoController,
configuration: SubtitleViewConfiguration(
style: subtileTextStyle(ref)),
)),
),
AnimatedOpacity(
curve: Curves.easeInOut,
opacity: visible ? 1.0 : 0.0,
duration: controlsTransitionDuration,
onEnd: () {
if (!visible) {
setState(() {
mount = false;
});
} }
}, }
child: Stack( : null,
clipBehavior: Clip.none, child: GestureDetector(
alignment: Alignment.bottomCenter, onTapUp: !toggleFullscreenOnDoublePress
children: [ ? null
// Top gradient. : (e) {
final now = DateTime.now();
final difference = now.difference(last);
last = now;
if (difference < const Duration(milliseconds: 400)) {
setFullScreen();
}
},
onPanUpdate: modifyVolumeOnScroll
? (e) {
if (e.delta.dy > 0) {
final volume =
widget.videoController.player.state.volume - 5.0;
widget.videoController.player
.setVolume(volume.clamp(0.0, 100.0));
}
if (e.delta.dy < 0) {
final volume =
widget.videoController.player.state.volume + 5.0;
widget.videoController.player
.setVolume(volume.clamp(0.0, 100.0));
}
}
: null,
child: MouseRegion(
onHover: (_) => onHover(),
onEnter: (_) => onEnter(),
onExit: (_) => onExit(),
child: Stack(
children: [
AnimatedOpacity(
curve: Curves.easeInOut,
opacity: visible ? 1.0 : 0.0,
duration: controlsTransitionDuration,
onEnd: () {
if (!visible) {
setState(() {
mount = false;
});
}
},
child: Stack(
clipBehavior: Clip.none,
alignment: Alignment.bottomCenter,
children: [
// Top gradient.
Container( Container(
decoration: const BoxDecoration( decoration: const BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
begin: Alignment.topCenter, begin: Alignment.topCenter,
end: Alignment.bottomCenter, end: Alignment.bottomCenter,
stops: [ stops: [
0.0, 0.0,
0.2, 0.2,
], ],
colors: [ colors: [
Color(0x61000000), Color(0x61000000),
Color(0x00000000), Color(0x00000000),
], ],
),
),
),
// Bottom gradient.
Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [
0.5,
1.0,
],
colors: [
Color(0x00000000),
Color(0x61000000),
],
),
),
),
if (mount)
Padding(
padding: (
// Add padding in fullscreen!
isFullscreen(context)
? MediaQuery.of(context).padding
: EdgeInsets.zero),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
widget.topButtonBarWidget,
// Only display [primaryButtonBar] if [buffering] is false.
Expanded(
child: AnimatedOpacity(
curve: Curves.easeInOut,
opacity: buffering
? 0.0
: !showSwipeDuration
? 0.0
: 1.0,
duration: controlsTransitionDuration,
child: Center(
child: seekIndicatorTextWidget(
Duration(seconds: swipeDuration),
widget.videoController.player
.state.position))),
),
widget.seekToWidget,
Transform.translate(
offset: Offset.zero,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 5),
child: CustomSeekBar(
onSeekStart: (value) {
setState(() {
swipeDuration = value.inSeconds;
showSwipeDuration = true;
widget.tempDuration(widget
.videoController
.player
.state
.position +
value);
});
_timer?.cancel();
},
onSeekEnd: (value) {
_timer = Timer(
controlsHoverDuration,
() {
if (mounted) {
setState(() {
visible = false;
});
}
},
);
setState(() {
showSwipeDuration = false;
});
widget.tempDuration(null);
},
player: widget.videoController.player,
),
),
),
widget.bottomButtonBarWidget
],
),
),
],
),
),
// Buffering Indicator.
IgnorePointer(
child: Padding(
padding: (
// Add padding in fullscreen!
isFullscreen(context)
? MediaQuery.of(context).padding
: EdgeInsets.zero),
child: Column(
children: [
Container(
height: buttonBarHeight,
margin: const EdgeInsets.all(0),
),
Expanded(
child: Center(
child: Center(
child: TweenAnimationBuilder<double>(
tween: Tween<double>(
begin: 0.0,
end: buffering ? 1.0 : 0.0,
),
duration: controlsTransitionDuration,
builder: (context, value, child) {
// Only mount the buffering indicator if the opacity is greater than 0.0.
// This has been done to prevent redundant resource usage in [CircularProgressIndicator].
if (value > 0.0) {
return Opacity(
opacity: value,
child: child!,
);
}
return const SizedBox.shrink();
},
child: const CircularProgressIndicator(
color: Color(0xFFFFFFFF),
),
), ),
), ),
), ),
), // Bottom gradient.
Container(
height: buttonBarHeight, Container(
margin: bottomButtonBarMargin, decoration: const BoxDecoration(
), gradient: LinearGradient(
], begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [
0.5,
1.0,
],
colors: [
Color(0x00000000),
Color(0x61000000),
],
),
),
),
if (mount)
Padding(
padding: (
// Add padding in fullscreen!
isFullscreen(context)
? MediaQuery.of(context).padding
: EdgeInsets.zero),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
widget.topButtonBarWidget,
// Only display [primaryButtonBar] if [buffering] is false.
Expanded(
child: AnimatedOpacity(
curve: Curves.easeInOut,
opacity: buffering
? 0.0
: !showSwipeDuration
? 0.0
: 1.0,
duration: controlsTransitionDuration,
child: Center(
child: seekIndicatorTextWidget(
Duration(
seconds: swipeDuration),
widget.videoController.player
.state.position))),
),
widget.seekToWidget,
Transform.translate(
offset: Offset.zero,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 5),
child: CustomSeekBar(
onSeekStart: (value) {
setState(() {
swipeDuration = value.inSeconds;
showSwipeDuration = true;
widget.tempDuration(widget
.videoController
.player
.state
.position +
value);
});
_timer?.cancel();
},
onSeekEnd: (value) {
_timer = Timer(
controlsHoverDuration,
() {
if (mounted) {
setState(() {
visible = false;
});
}
},
);
setState(() {
showSwipeDuration = false;
});
widget.tempDuration(null);
},
player: widget.videoController.player,
),
),
),
widget.bottomButtonBarWidget
],
),
),
],
),
), ),
), // Buffering Indicator.
IgnorePointer(
child: Padding(
padding: (
// Add padding in fullscreen!
isFullscreen(context)
? MediaQuery.of(context).padding
: EdgeInsets.zero),
child: Column(
children: [
Container(
height: buttonBarHeight,
margin: const EdgeInsets.all(0),
),
Expanded(
child: Center(
child: Center(
child: TweenAnimationBuilder<double>(
tween: Tween<double>(
begin: 0.0,
end: buffering ? 1.0 : 0.0,
),
duration: controlsTransitionDuration,
builder: (context, value, child) {
// Only mount the buffering indicator if the opacity is greater than 0.0.
// This has been done to prevent redundant resource usage in [CircularProgressIndicator].
if (value > 0.0) {
return Opacity(
opacity: value,
child: child!,
);
}
return const SizedBox.shrink();
},
child: const CircularProgressIndicator(
color: Color(0xFFFFFFFF),
),
),
),
),
),
Container(
height: buttonBarHeight,
margin: bottomButtonBarMargin,
),
],
),
),
),
],
), ),
], ),
), ),
), ),
), ),
), ],
), ),
); );
} }

View file

@ -286,374 +286,381 @@ class _MobileControllerWidgetState
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Focus( return Stack(
autofocus: true, children: [
child: Stack( Consumer(
clipBehavior: Clip.none, builder: (context, ref, _) => Positioned(
alignment: Alignment.center, child: CustomSubtitleView(
children: [ controller: widget.videoController,
// // Controls: configuration:
AnimatedOpacity( SubtitleViewConfiguration(style: subtileTextStyle(ref)),
curve: Curves.easeInOut, )),
opacity: visible ? 1.0 : 0.0, ),
duration: controlsTransitionDuration, Focus(
onEnd: () { autofocus: true,
setState(() { child: Stack(
if (!visible) { clipBehavior: Clip.none,
mount = false; alignment: Alignment.center,
} children: [
}); // // Controls:
}, AnimatedOpacity(
child: Stack( curve: Curves.easeInOut,
clipBehavior: Clip.none, opacity: visible ? 1.0 : 0.0,
alignment: Alignment.center, duration: controlsTransitionDuration,
children: [ onEnd: () {
Consumer( setState(() {
builder: (context, ref, _) => Positioned( if (!visible) {
child: CustomSubtitleView( mount = false;
controller: widget.videoController, }
configuration: });
SubtitleViewConfiguration(style: subtileTextStyle(ref)), },
)), child: Stack(
), clipBehavior: Clip.none,
Positioned.fill( alignment: Alignment.center,
child: Container( children: [
color: backdropColor, Positioned.fill(
), child: Container(
), color: backdropColor,
// We are adding 16.0 boundary around the actual controls (which contain the vertical drag gesture detectors). ),
// This will make the hit-test on edges (e.g. swiping to: show status-bar, show navigation-bar, go back in navigation) not activate the swipe gesture annoyingly.
Positioned.fill(
left: 16.0,
top: 16.0,
right: 16.0,
bottom: 16.0,
child: GestureDetector(
onTap: onTap,
onDoubleTapDown: _handleTapDown,
onDoubleTap: () {
if (_tapPosition != null &&
_tapPosition!.dx >
MediaQuery.of(context).size.width / 2) {
onDoubleTapSeekForward();
} else {
onDoubleTapSeekBackward();
}
},
onHorizontalDragUpdate: (details) {
onHorizontalDragUpdate(details);
},
onHorizontalDragEnd: (details) {
onHorizontalDragEnd();
},
onVerticalDragUpdate: (e) async {
final delta = e.delta.dy;
final Offset position = e.localPosition;
if (position.dx <=
MediaQuery.of(context).size.width / 2) {
// Left side of screen swiped
final brightness = _brightnessValue.value -
delta / verticalGestureSensitivity;
final result = brightness.clamp(0.0, 1.0);
setBrightness(result);
} else {
// Right side of screen swiped
final volume = _volumeValue.value -
delta / verticalGestureSensitivity;
final result = volume.clamp(0.0, 1.0);
setVolume(result);
}
},
child: Container(
color: const Color(0x00000000),
), ),
), // We are adding 16.0 boundary around the actual controls (which contain the vertical drag gesture detectors).
), // This will make the hit-test on edges (e.g. swiping to: show status-bar, show navigation-bar, go back in navigation) not activate the swipe gesture annoyingly.
if (mount) Positioned.fill(
Padding( left: 16.0,
padding: ( top: 16.0,
// Add padding in fullscreen! right: 16.0,
isFullscreen(context) bottom: 16.0,
? MediaQuery.of(context).padding child: GestureDetector(
: EdgeInsets.zero), onTap: onTap,
child: Column( onDoubleTapDown: _handleTapDown,
mainAxisSize: MainAxisSize.min, onDoubleTap: () {
mainAxisAlignment: MainAxisAlignment.start, if (_tapPosition != null &&
crossAxisAlignment: CrossAxisAlignment.end, _tapPosition!.dx >
children: [ MediaQuery.of(context).size.width / 2) {
widget.topButtonBarWidget, onDoubleTapSeekForward();
// Only display [primaryButtonBar] if [buffering] is false. } else {
Expanded( onDoubleTapSeekBackward();
child: AnimatedOpacity( }
curve: Curves.easeInOut, },
opacity: buffering onHorizontalDragUpdate: (details) {
? 0.0 onHorizontalDragUpdate(details);
: showSwipeDuration },
? 0.0 onHorizontalDragEnd: (details) {
: 1.0, onHorizontalDragEnd();
duration: controlsTransitionDuration, },
child: Center( onVerticalDragUpdate: (e) async {
child: Row( final delta = e.delta.dy;
children: mobilePrimaryButtonBar( final Offset position = e.localPosition;
context,
widget.videoStatekey, if (position.dx <=
widget.streamController, MediaQuery.of(context).size.width / 2) {
widget.videoController)), // Left side of screen swiped
),
), final brightness = _brightnessValue.value -
delta / verticalGestureSensitivity;
final result = brightness.clamp(0.0, 1.0);
setBrightness(result);
} else {
// Right side of screen swiped
final volume = _volumeValue.value -
delta / verticalGestureSensitivity;
final result = volume.clamp(0.0, 1.0);
setVolume(result);
}
},
child: Container(
color: const Color(0x00000000),
), ),
Stack( ),
alignment: Alignment.bottomCenter, ),
if (mount)
Padding(
padding: (
// Add padding in fullscreen!
isFullscreen(context)
? MediaQuery.of(context).padding
: EdgeInsets.zero),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
Padding( widget.topButtonBarWidget,
padding: const EdgeInsets.only(bottom: 10), // Only display [primaryButtonBar] if [buffering] is false.
child: CustomSeekBar( Expanded(
onSeekStart: (value) { child: AnimatedOpacity(
setState(() { curve: Curves.easeInOut,
swipeDuration = value.inSeconds; opacity: buffering
showSwipeDuration = true; ? 0.0
}); : showSwipeDuration
_timer?.cancel(); ? 0.0
}, : 1.0,
onSeekEnd: (value) { duration: controlsTransitionDuration,
_timer = Timer( child: Center(
controlsHoverDuration, child: Row(
() { children: mobilePrimaryButtonBar(
if (mounted) { context,
setState(() { widget.videoStatekey,
visible = false; widget.streamController,
}); widget.videoController)),
} ),
},
);
setState(() {
showSwipeDuration = false;
});
},
player: widget.videoController.player,
), ),
), ),
widget.bottomButtonBarWidget Stack(
alignment: Alignment.bottomCenter,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: CustomSeekBar(
onSeekStart: (value) {
setState(() {
swipeDuration = value.inSeconds;
showSwipeDuration = true;
});
_timer?.cancel();
},
onSeekEnd: (value) {
_timer = Timer(
controlsHoverDuration,
() {
if (mounted) {
setState(() {
visible = false;
});
}
},
);
setState(() {
showSwipeDuration = false;
});
},
player: widget.videoController.player,
),
),
widget.bottomButtonBarWidget
],
),
], ],
), ),
], ),
), ],
), ),
], ),
), // // Double-Tap Seek Seek-Bar:
), if (!mount)
// // Double-Tap Seek Seek-Bar: if (_mountSeekBackwardButton ||
if (!mount) _mountSeekForwardButton ||
if (_mountSeekBackwardButton || showSwipeDuration)
_mountSeekForwardButton || Column(
showSwipeDuration)
Column(
children: [
const Spacer(),
Stack(
alignment: Alignment.bottomCenter,
children: [ children: [
Padding( const Spacer(),
padding: const EdgeInsets.only(bottom: 10), Stack(
child: CustomSeekBar( alignment: Alignment.bottomCenter,
delta: _seekBarDeltaValueNotifier, children: [
player: widget.videoController.player), Padding(
padding: const EdgeInsets.only(bottom: 10),
child: CustomSeekBar(
delta: _seekBarDeltaValueNotifier,
player: widget.videoController.player),
),
],
), ),
], ],
), ),
], // // Buffering Indicator.
), IgnorePointer(
// // Buffering Indicator. child: Padding(
IgnorePointer( padding: (
child: Padding( // Add padding in fullscreen!
padding: ( isFullscreen(context)
// Add padding in fullscreen! ? MediaQuery.of(context).padding
isFullscreen(context) : EdgeInsets.zero),
? MediaQuery.of(context).padding child: Column(
: EdgeInsets.zero), children: [
child: Column( Container(
children: [ height: buttonBarHeight,
Container( margin: const EdgeInsets.all(0),
height: buttonBarHeight, ),
margin: const EdgeInsets.all(0), Expanded(
), child: Center(
Expanded( child: TweenAnimationBuilder<double>(
child: Center( tween: Tween<double>(
child: TweenAnimationBuilder<double>( begin: 0.0,
tween: Tween<double>( end: buffering ? 1.0 : 0.0,
begin: 0.0, ),
end: buffering ? 1.0 : 0.0, duration: controlsTransitionDuration,
), builder: (context, value, child) {
duration: controlsTransitionDuration, // Only mount the buffering indicator if the opacity is greater than 0.0.
builder: (context, value, child) { // This has been done to prevent redundant resource usage in [CircularProgressIndicator].
// Only mount the buffering indicator if the opacity is greater than 0.0. if (value > 0.0) {
// This has been done to prevent redundant resource usage in [CircularProgressIndicator]. return Opacity(
if (value > 0.0) { opacity: value,
return Opacity( child: child!,
opacity: value, );
child: child!, }
); return const SizedBox.shrink();
} },
return const SizedBox.shrink(); child: const CircularProgressIndicator(
}, color: Color(0xFFFFFFFF),
child: const CircularProgressIndicator( ),
color: Color(0xFFFFFFFF), ),
), ),
), ),
), Container(
height: buttonBarHeight,
margin: bottomButtonBarMargin,
),
],
), ),
Container( ),
height: buttonBarHeight, ),
margin: bottomButtonBarMargin, // // Volume Indicator.
), IgnorePointer(
], child: ValueListenableBuilder(
valueListenable: _volumeIndicator,
builder: (context, value, child) => AnimatedOpacity(
curve: Curves.easeInOut,
opacity: value ? 1.0 : 0.0,
duration: controlsTransitionDuration,
child: MediaIndicatorBuilder(
value: _volumeValue, isVolumeIndicator: true)),
),
),
// // Brightness Indicator.
IgnorePointer(
child: ValueListenableBuilder(
valueListenable: _brightnessIndicator,
builder: (context, value, child) => AnimatedOpacity(
curve: Curves.easeInOut,
opacity: value ? 1.0 : 0.0,
duration: controlsTransitionDuration,
child: MediaIndicatorBuilder(
value: _brightnessValue, isVolumeIndicator: false)),
),
),
// Seek Indicator.
IgnorePointer(
child: AnimatedOpacity(
duration: controlsTransitionDuration,
opacity: showSwipeDuration ? 1 : 0,
child: seekIndicatorTextWidget(
Duration(seconds: swipeDuration),
widget.videoController.player.state.position)),
), ),
),
),
// // Volume Indicator.
IgnorePointer(
child: ValueListenableBuilder(
valueListenable: _volumeIndicator,
builder: (context, value, child) => AnimatedOpacity(
curve: Curves.easeInOut,
opacity: value ? 1.0 : 0.0,
duration: controlsTransitionDuration,
child: MediaIndicatorBuilder(
value: _volumeValue, isVolumeIndicator: true)),
),
),
// // Brightness Indicator.
IgnorePointer(
child: ValueListenableBuilder(
valueListenable: _brightnessIndicator,
builder: (context, value, child) => AnimatedOpacity(
curve: Curves.easeInOut,
opacity: value ? 1.0 : 0.0,
duration: controlsTransitionDuration,
child: MediaIndicatorBuilder(
value: _brightnessValue, isVolumeIndicator: false)),
),
),
// Seek Indicator.
IgnorePointer(
child: AnimatedOpacity(
duration: controlsTransitionDuration,
opacity: showSwipeDuration ? 1 : 0,
child: seekIndicatorTextWidget(Duration(seconds: swipeDuration),
widget.videoController.player.state.position)),
),
// Double-Tap Seek Button(s): // Double-Tap Seek Button(s):
if (_mountSeekBackwardButton || _mountSeekForwardButton) if (_mountSeekBackwardButton || _mountSeekForwardButton)
Positioned.fill( Positioned.fill(
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
child: _mountSeekBackwardButton child: _mountSeekBackwardButton
? TweenAnimationBuilder<double>( ? TweenAnimationBuilder<double>(
tween: Tween<double>( tween: Tween<double>(
begin: 0.0, begin: 0.0,
end: _hideSeekBackwardButton ? 0.0 : 1.0, end: _hideSeekBackwardButton ? 0.0 : 1.0,
), ),
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
builder: (context, value, child) => Opacity( builder: (context, value, child) => Opacity(
opacity: value, opacity: value,
child: child, child: child,
), ),
onEnd: () { onEnd: () {
if (_hideSeekBackwardButton) { if (_hideSeekBackwardButton) {
setState(() { setState(() {
_hideSeekBackwardButton = false; _hideSeekBackwardButton = false;
_mountSeekBackwardButton = false; _mountSeekBackwardButton = false;
}); });
} }
},
child: _BackwardSeekIndicator(
onChanged: (value) {
setState(() {
_seekBarDeltaValueNotifier = widget
.videoController
.player
.state
.position -
value;
});
}, },
onSubmitted: (value) { child: _BackwardSeekIndicator(
setState(() { onChanged: (value) {
_hideSeekBackwardButton = true; setState(() {
}); _seekBarDeltaValueNotifier = widget
var result = widget.videoController.player .videoController
.state.position - .player
value; .state
result = result.clamp( .position -
Duration.zero, value;
widget });
.videoController.player.state.duration, },
); onSubmitted: (value) {
widget.videoController.player.seek(result); setState(() {
_hideSeekBackwardButton = true;
});
var result = widget.videoController.player
.state.position -
value;
result = result.clamp(
Duration.zero,
widget.videoController.player.state
.duration,
);
widget.videoController.player
.seek(result);
},
skipDuration: skipDuration),
)
: const SizedBox(),
),
Expanded(
child: _mountSeekForwardButton
? TweenAnimationBuilder<double>(
tween: Tween<double>(
begin: 0.0,
end: _hideSeekForwardButton ? 0.0 : 1.0,
),
duration: const Duration(milliseconds: 200),
builder: (context, value, child) => Opacity(
opacity: value,
child: child,
),
onEnd: () {
if (_hideSeekForwardButton) {
setState(() {
_hideSeekForwardButton = false;
_mountSeekForwardButton = false;
});
}
}, },
skipDuration: skipDuration), child: _ForwardSeekIndicator(
) onChanged: (value) {
: const SizedBox(), setState(() {
_seekBarDeltaValueNotifier = widget
.videoController
.player
.state
.position +
value;
});
},
onSubmitted: (value) {
setState(() {
_hideSeekForwardButton = true;
});
var result = widget.videoController.player
.state.position +
value;
result = result.clamp(
Duration.zero,
widget.videoController.player.state
.duration,
);
widget.videoController.player
.seek(result);
},
skipDuration: skipDuration),
)
: const SizedBox(),
),
],
), ),
Expanded( ),
child: _mountSeekForwardButton ],
? TweenAnimationBuilder<double>( ),
tween: Tween<double>( ),
begin: 0.0, ],
end: _hideSeekForwardButton ? 0.0 : 1.0,
),
duration: const Duration(milliseconds: 200),
builder: (context, value, child) => Opacity(
opacity: value,
child: child,
),
onEnd: () {
if (_hideSeekForwardButton) {
setState(() {
_hideSeekForwardButton = false;
_mountSeekForwardButton = false;
});
}
},
child: _ForwardSeekIndicator(
onChanged: (value) {
setState(() {
_seekBarDeltaValueNotifier = widget
.videoController
.player
.state
.position +
value;
});
},
onSubmitted: (value) {
setState(() {
_hideSeekForwardButton = true;
});
var result = widget.videoController.player
.state.position +
value;
result = result.clamp(
Duration.zero,
widget
.videoController.player.state.duration,
);
widget.videoController.player.seek(result);
},
skipDuration: skipDuration),
)
: const SizedBox(),
),
],
),
),
],
),
); );
} }
} }

View file

@ -144,7 +144,7 @@ class ColorSettingWidget extends ConsumerStatefulWidget {
class _ColorSettingWidgetState extends ConsumerState<ColorSettingWidget> { class _ColorSettingWidgetState extends ConsumerState<ColorSettingWidget> {
String selector = "text"; String selector = "text";
Widget button(String text, Color color) { Widget button(String text, String value, Color color) {
return ElevatedButton( return ElevatedButton(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(0), padding: const EdgeInsets.all(0),
@ -154,7 +154,7 @@ class _ColorSettingWidgetState extends ConsumerState<ColorSettingWidget> {
shadowColor: Colors.transparent), shadowColor: Colors.transparent),
onPressed: () { onPressed: () {
setState(() { setState(() {
selector = text.toLowerCase(); selector = value;
}); });
}, },
child: Column( child: Column(
@ -175,9 +175,7 @@ class _ColorSettingWidgetState extends ConsumerState<ColorSettingWidget> {
Text("#${color.hexCode}", style: TextStyle(color: context.textColor)), Text("#${color.hexCode}", style: TextStyle(color: context.textColor)),
Icon( Icon(
Icons.arrow_drop_down, Icons.arrow_drop_down,
color: selector != text.toLowerCase() color: selector != value ? Colors.transparent : context.textColor,
? Colors.transparent
: context.textColor,
) )
], ],
), ),
@ -218,12 +216,15 @@ class _ColorSettingWidgetState extends ConsumerState<ColorSettingWidget> {
), ),
Row( Row(
children: [ children: [
Expanded(flex: 3, child: button(context.l10n.text, textColor)),
Expanded( Expanded(
flex: 3, child: button(context.l10n.border, borderColor)), flex: 3, child: button(context.l10n.text, "text", textColor)),
Expanded( Expanded(
flex: 3, flex: 3,
child: button(context.l10n.background, backgroundColor)), child: button(context.l10n.border, "border", borderColor)),
Expanded(
flex: 3,
child: button(
context.l10n.background, "backgroud", backgroundColor)),
], ],
), ),
Padding( Padding(

View file

@ -9,10 +9,12 @@ import 'package:mangayomi/utils/date.dart';
import 'package:mangayomi/utils/extensions/build_context_extensions.dart'; import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
Widget btnToShowChapterListDialog( Widget btnToShowChapterListDialog(
BuildContext context, String title, Chapter chapter) { BuildContext context, String title, Chapter chapter,
{void Function(bool)? onChanged}) {
return IconButton( return IconButton(
onPressed: () { onPressed: () async {
showDialog( onChanged?.call(false);
await showDialog(
context: context, context: context,
builder: (context) { builder: (context) {
return AlertDialog( return AlertDialog(
@ -22,6 +24,7 @@ Widget btnToShowChapterListDialog(
child: ChapterListWidget(chapter: chapter)), child: ChapterListWidget(chapter: chapter)),
); );
}); });
onChanged?.call(true);
}, },
icon: const Icon(Icons.format_list_numbered_outlined)); icon: const Icon(Icons.format_list_numbered_outlined));
} }
@ -60,7 +63,6 @@ class _ChapterListWidgetState extends State<ChapterListWidget> {
return DraggableScrollbarWidget( return DraggableScrollbarWidget(
controller: controller, controller: controller,
child: ListView.builder( child: ListView.builder(
shrinkWrap: true,
padding: const EdgeInsets.symmetric(vertical: 2), padding: const EdgeInsets.symmetric(vertical: 2),
controller: controller, controller: controller,
itemCount: chapterList.length, itemCount: chapterList.length,

View file

@ -166,7 +166,8 @@ class AppearanceScreen extends ConsumerWidget {
child: Column( child: Column(
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.symmetric(
vertical: 12, horizontal: 8),
child: TextField( child: TextField(
onChanged: (v) { onChanged: (v) {
setState(() { setState(() {
@ -209,7 +210,6 @@ class AppearanceScreen extends ConsumerWidget {
controller: controller, controller: controller,
child: ListView.builder( child: ListView.builder(
controller: controller, controller: controller,
shrinkWrap: true,
itemCount: values.length, itemCount: values.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final value = values[index]; final value = values[index];

View file

@ -6,7 +6,6 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <desktop_webview_window/desktop_webview_window_plugin.h>
#include <isar_flutter_libs/isar_flutter_libs_plugin.h> #include <isar_flutter_libs/isar_flutter_libs_plugin.h>
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h> #include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
#include <media_kit_video/media_kit_video_plugin.h> #include <media_kit_video/media_kit_video_plugin.h>
@ -16,9 +15,6 @@
#include <window_to_front/window_to_front_plugin.h> #include <window_to_front/window_to_front_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) desktop_webview_window_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopWebviewWindowPlugin");
desktop_webview_window_plugin_register_with_registrar(desktop_webview_window_registrar);
g_autoptr(FlPluginRegistrar) isar_flutter_libs_registrar = g_autoptr(FlPluginRegistrar) isar_flutter_libs_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "IsarFlutterLibsPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "IsarFlutterLibsPlugin");
isar_flutter_libs_plugin_register_with_registrar(isar_flutter_libs_registrar); isar_flutter_libs_plugin_register_with_registrar(isar_flutter_libs_registrar);

View file

@ -3,7 +3,6 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
desktop_webview_window
isar_flutter_libs isar_flutter_libs
media_kit_libs_linux media_kit_libs_linux
media_kit_video media_kit_video