mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-01-11 22:40:36 +00:00
fix
This commit is contained in:
parent
fe29eb6ecc
commit
32dbbd5e0e
9 changed files with 623 additions and 603 deletions
|
|
@ -921,7 +921,17 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
),
|
||||
Row(children: [
|
||||
btnToShowChapterListDialog(
|
||||
context, context.l10n.episodes, widget.episode),
|
||||
context,
|
||||
context.l10n.episodes,
|
||||
widget.episode,
|
||||
onChanged: (v) {
|
||||
if (v) {
|
||||
_player.play();
|
||||
} else {
|
||||
_player.pause();
|
||||
}
|
||||
},
|
||||
),
|
||||
// IconButton(
|
||||
// onPressed: () {
|
||||
// showDialog(
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class SubtitleSettingsState extends _$SubtitleSettingsState {
|
|||
@override
|
||||
PlayerSubtitleSettings build() {
|
||||
final subSets = isar.settings.getSync(227)!.playerSubtitleSettings;
|
||||
if (subSets == null) {
|
||||
if (subSets == null || subSets.backgroundColorA == null) {
|
||||
set(PlayerSubtitleSettings(), true);
|
||||
return PlayerSubtitleSettings();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,249 +189,254 @@ class _DesktopControllerWidgetState extends State<DesktopControllerWidget> {
|
|||
const SingleActivator(LogicalKeyboardKey.escape): () =>
|
||||
setFullScreen(value: false),
|
||||
},
|
||||
child: Focus(
|
||||
autofocus: true,
|
||||
child: Listener(
|
||||
onPointerSignal: modifyVolumeOnScroll
|
||||
? (e) {
|
||||
if (e is PointerScrollEvent) {
|
||||
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: GestureDetector(
|
||||
onTapUp: !toggleFullscreenOnDoublePress
|
||||
? null
|
||||
: (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: [
|
||||
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(
|
||||
children: [
|
||||
Consumer(
|
||||
builder: (context, ref, _) => Positioned(
|
||||
child: CustomSubtitleView(
|
||||
controller: widget.videoController,
|
||||
configuration:
|
||||
SubtitleViewConfiguration(style: subtileTextStyle(ref)),
|
||||
)),
|
||||
),
|
||||
Focus(
|
||||
autofocus: true,
|
||||
child: Listener(
|
||||
onPointerSignal: modifyVolumeOnScroll
|
||||
? (e) {
|
||||
if (e is PointerScrollEvent) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.bottomCenter,
|
||||
children: [
|
||||
// Top gradient.
|
||||
}
|
||||
: null,
|
||||
child: GestureDetector(
|
||||
onTapUp: !toggleFullscreenOnDoublePress
|
||||
? null
|
||||
: (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(
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
stops: [
|
||||
0.0,
|
||||
0.2,
|
||||
],
|
||||
colors: [
|
||||
Color(0x61000000),
|
||||
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),
|
||||
),
|
||||
Container(
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
stops: [
|
||||
0.0,
|
||||
0.2,
|
||||
],
|
||||
colors: [
|
||||
Color(0x61000000),
|
||||
Color(0x00000000),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: buttonBarHeight,
|
||||
margin: bottomButtonBarMargin,
|
||||
),
|
||||
],
|
||||
// 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),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: buttonBarHeight,
|
||||
margin: bottomButtonBarMargin,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,374 +286,381 @@ class _MobileControllerWidgetState
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Focus(
|
||||
autofocus: true,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
// // Controls:
|
||||
AnimatedOpacity(
|
||||
curve: Curves.easeInOut,
|
||||
opacity: visible ? 1.0 : 0.0,
|
||||
duration: controlsTransitionDuration,
|
||||
onEnd: () {
|
||||
setState(() {
|
||||
if (!visible) {
|
||||
mount = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Consumer(
|
||||
builder: (context, ref, _) => Positioned(
|
||||
child: CustomSubtitleView(
|
||||
controller: widget.videoController,
|
||||
configuration:
|
||||
SubtitleViewConfiguration(style: subtileTextStyle(ref)),
|
||||
)),
|
||||
),
|
||||
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),
|
||||
return Stack(
|
||||
children: [
|
||||
Consumer(
|
||||
builder: (context, ref, _) => Positioned(
|
||||
child: CustomSubtitleView(
|
||||
controller: widget.videoController,
|
||||
configuration:
|
||||
SubtitleViewConfiguration(style: subtileTextStyle(ref)),
|
||||
)),
|
||||
),
|
||||
Focus(
|
||||
autofocus: true,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
// // Controls:
|
||||
AnimatedOpacity(
|
||||
curve: Curves.easeInOut,
|
||||
opacity: visible ? 1.0 : 0.0,
|
||||
duration: controlsTransitionDuration,
|
||||
onEnd: () {
|
||||
setState(() {
|
||||
if (!visible) {
|
||||
mount = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
color: backdropColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
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: Row(
|
||||
children: mobilePrimaryButtonBar(
|
||||
context,
|
||||
widget.videoStatekey,
|
||||
widget.streamController,
|
||||
widget.videoController)),
|
||||
),
|
||||
),
|
||||
// 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),
|
||||
),
|
||||
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: [
|
||||
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.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: Row(
|
||||
children: mobilePrimaryButtonBar(
|
||||
context,
|
||||
widget.videoStatekey,
|
||||
widget.streamController,
|
||||
widget.videoController)),
|
||||
),
|
||||
),
|
||||
),
|
||||
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)
|
||||
if (_mountSeekBackwardButton ||
|
||||
_mountSeekForwardButton ||
|
||||
showSwipeDuration)
|
||||
Column(
|
||||
children: [
|
||||
const Spacer(),
|
||||
Stack(
|
||||
alignment: Alignment.bottomCenter,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// // Double-Tap Seek Seek-Bar:
|
||||
if (!mount)
|
||||
if (_mountSeekBackwardButton ||
|
||||
_mountSeekForwardButton ||
|
||||
showSwipeDuration)
|
||||
Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: CustomSeekBar(
|
||||
delta: _seekBarDeltaValueNotifier,
|
||||
player: widget.videoController.player),
|
||||
const Spacer(),
|
||||
Stack(
|
||||
alignment: Alignment.bottomCenter,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: CustomSeekBar(
|
||||
delta: _seekBarDeltaValueNotifier,
|
||||
player: widget.videoController.player),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
// // 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: 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),
|
||||
// // 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: 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
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):
|
||||
if (_mountSeekBackwardButton || _mountSeekForwardButton)
|
||||
Positioned.fill(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _mountSeekBackwardButton
|
||||
? TweenAnimationBuilder<double>(
|
||||
tween: Tween<double>(
|
||||
begin: 0.0,
|
||||
end: _hideSeekBackwardButton ? 0.0 : 1.0,
|
||||
),
|
||||
duration: const Duration(milliseconds: 200),
|
||||
builder: (context, value, child) => Opacity(
|
||||
opacity: value,
|
||||
child: child,
|
||||
),
|
||||
onEnd: () {
|
||||
if (_hideSeekBackwardButton) {
|
||||
setState(() {
|
||||
_hideSeekBackwardButton = false;
|
||||
_mountSeekBackwardButton = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
child: _BackwardSeekIndicator(
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_seekBarDeltaValueNotifier = widget
|
||||
.videoController
|
||||
.player
|
||||
.state
|
||||
.position -
|
||||
value;
|
||||
});
|
||||
// Double-Tap Seek Button(s):
|
||||
if (_mountSeekBackwardButton || _mountSeekForwardButton)
|
||||
Positioned.fill(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _mountSeekBackwardButton
|
||||
? TweenAnimationBuilder<double>(
|
||||
tween: Tween<double>(
|
||||
begin: 0.0,
|
||||
end: _hideSeekBackwardButton ? 0.0 : 1.0,
|
||||
),
|
||||
duration: const Duration(milliseconds: 200),
|
||||
builder: (context, value, child) => Opacity(
|
||||
opacity: value,
|
||||
child: child,
|
||||
),
|
||||
onEnd: () {
|
||||
if (_hideSeekBackwardButton) {
|
||||
setState(() {
|
||||
_hideSeekBackwardButton = false;
|
||||
_mountSeekBackwardButton = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
onSubmitted: (value) {
|
||||
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);
|
||||
child: _BackwardSeekIndicator(
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_seekBarDeltaValueNotifier = widget
|
||||
.videoController
|
||||
.player
|
||||
.state
|
||||
.position -
|
||||
value;
|
||||
});
|
||||
},
|
||||
onSubmitted: (value) {
|
||||
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),
|
||||
)
|
||||
: const SizedBox(),
|
||||
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(),
|
||||
),
|
||||
],
|
||||
),
|
||||
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(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ class ColorSettingWidget extends ConsumerStatefulWidget {
|
|||
class _ColorSettingWidgetState extends ConsumerState<ColorSettingWidget> {
|
||||
String selector = "text";
|
||||
|
||||
Widget button(String text, Color color) {
|
||||
Widget button(String text, String value, Color color) {
|
||||
return ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.all(0),
|
||||
|
|
@ -154,7 +154,7 @@ class _ColorSettingWidgetState extends ConsumerState<ColorSettingWidget> {
|
|||
shadowColor: Colors.transparent),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
selector = text.toLowerCase();
|
||||
selector = value;
|
||||
});
|
||||
},
|
||||
child: Column(
|
||||
|
|
@ -175,9 +175,7 @@ class _ColorSettingWidgetState extends ConsumerState<ColorSettingWidget> {
|
|||
Text("#${color.hexCode}", style: TextStyle(color: context.textColor)),
|
||||
Icon(
|
||||
Icons.arrow_drop_down,
|
||||
color: selector != text.toLowerCase()
|
||||
? Colors.transparent
|
||||
: context.textColor,
|
||||
color: selector != value ? Colors.transparent : context.textColor,
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
@ -218,12 +216,15 @@ class _ColorSettingWidgetState extends ConsumerState<ColorSettingWidget> {
|
|||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(flex: 3, child: button(context.l10n.text, textColor)),
|
||||
Expanded(
|
||||
flex: 3, child: button(context.l10n.border, borderColor)),
|
||||
flex: 3, child: button(context.l10n.text, "text", textColor)),
|
||||
Expanded(
|
||||
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(
|
||||
|
|
|
|||
|
|
@ -9,10 +9,12 @@ import 'package:mangayomi/utils/date.dart';
|
|||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
|
||||
Widget btnToShowChapterListDialog(
|
||||
BuildContext context, String title, Chapter chapter) {
|
||||
BuildContext context, String title, Chapter chapter,
|
||||
{void Function(bool)? onChanged}) {
|
||||
return IconButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
onPressed: () async {
|
||||
onChanged?.call(false);
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
|
|
@ -22,6 +24,7 @@ Widget btnToShowChapterListDialog(
|
|||
child: ChapterListWidget(chapter: chapter)),
|
||||
);
|
||||
});
|
||||
onChanged?.call(true);
|
||||
},
|
||||
icon: const Icon(Icons.format_list_numbered_outlined));
|
||||
}
|
||||
|
|
@ -60,7 +63,6 @@ class _ChapterListWidgetState extends State<ChapterListWidget> {
|
|||
return DraggableScrollbarWidget(
|
||||
controller: controller,
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
controller: controller,
|
||||
itemCount: chapterList.length,
|
||||
|
|
|
|||
|
|
@ -166,7 +166,8 @@ class AppearanceScreen extends ConsumerWidget {
|
|||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12, horizontal: 8),
|
||||
child: TextField(
|
||||
onChanged: (v) {
|
||||
setState(() {
|
||||
|
|
@ -209,7 +210,6 @@ class AppearanceScreen extends ConsumerWidget {
|
|||
controller: controller,
|
||||
child: ListView.builder(
|
||||
controller: controller,
|
||||
shrinkWrap: true,
|
||||
itemCount: values.length,
|
||||
itemBuilder: (context, index) {
|
||||
final value = values[index];
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <desktop_webview_window/desktop_webview_window_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_video/media_kit_video_plugin.h>
|
||||
|
|
@ -16,9 +15,6 @@
|
|||
#include <window_to_front/window_to_front_plugin.h>
|
||||
|
||||
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 =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "IsarFlutterLibsPlugin");
|
||||
isar_flutter_libs_plugin_register_with_registrar(isar_flutter_libs_registrar);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
desktop_webview_window
|
||||
isar_flutter_libs
|
||||
media_kit_libs_linux
|
||||
media_kit_video
|
||||
|
|
|
|||
Loading…
Reference in a new issue