Skip to content

Commit

Permalink
✨ Add scrubbing to video player
Browse files Browse the repository at this point in the history
  • Loading branch information
wrngwrld committed Sep 28, 2024
1 parent 548b65a commit 25ce86c
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 130 deletions.
6 changes: 3 additions & 3 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.9.1;
MARKETING_VERSION = 0.9.2;
PRODUCT_BUNDLE_IDENTIFIER = com.wrngwrld.Chanyan;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down Expand Up @@ -525,7 +525,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.9.1;
MARKETING_VERSION = 0.9.2;
PRODUCT_BUNDLE_IDENTIFIER = com.wrngwrld.Chanyan;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down Expand Up @@ -554,7 +554,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.9.1;
MARKETING_VERSION = 0.9.2;
PRODUCT_BUNDLE_IDENTIFIER = com.wrngwrld.Chanyan;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/media_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ class _MediaPageState extends State<MediaPage> {
},
childCount: media.length,
),
scrollDirection: Axis.horizontal,
scrollDirection: Axis.vertical,
physics: const ClampingScrollPhysics(),
),
);
Expand Down
309 changes: 184 additions & 125 deletions lib/widgets/webm_player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:io';
import 'dart:ui';

import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_chan/API/save_videos.dart';
Expand Down Expand Up @@ -148,6 +149,47 @@ class VLCPlayerState extends State<VLCPlayer> {
}
}

void _onScrubbing(DragUpdateDetails details) {
try {
setState(() {
final double screenWidth = MediaQuery.of(context).size.width;

final int videoDurationInSeconds =
_videoPlayerController.value.duration.inSeconds;

double scrubSensitivity;

if (videoDurationInSeconds <= 15) {
scrubSensitivity = 70.0 / videoDurationInSeconds;
} else if (videoDurationInSeconds <= 30) {
scrubSensitivity = 100.0 / videoDurationInSeconds;
} else if (videoDurationInSeconds <= 300) {
scrubSensitivity = 200.0 / videoDurationInSeconds;
} else {
scrubSensitivity = 300.0 / videoDurationInSeconds;
}

final double delta = (details.delta.dx / screenWidth) *
scrubSensitivity *
videoDurationInSeconds;

int newSliderValue = (sliderValue + delta).round();

newSliderValue = newSliderValue.clamp(0, videoDurationInSeconds);

if ((newSliderValue - sliderValue).abs() >= 1) {
sliderValue = newSliderValue.toDouble();

if (_videoPlayerController.value.isInitialized) {
_videoPlayerController.setTime(sliderValue.toInt() * 1000);
}
}
});
} catch (e) {
print('Error during scrubbing: $e');
}
}

void _onSliderPositionChanged(double progress) {
try {
setState(() {
Expand Down Expand Up @@ -225,144 +267,161 @@ class VLCPlayerState extends State<VLCPlayer> {
const Center(
child: CupertinoActivityIndicator(),
),
VisibilityDetector(
key: ObjectKey(widget.video),
onVisibilityChanged: (visibility) {
if (visibility.visibleFraction < 0.5 &&
mounted &&
_videoPlayerController.value.isInitialized) {
_videoPlayerController.pause();

setState(() {
isVisible = false;
});
}
if (visibility.visibleFraction > 0.5 &&
mounted &&
_videoPlayerController.value.isInitialized) {
_videoPlayerController.play();

GestureDetector(
onTap: () {
setState(() {
galleryProvider
.setControlsVisible(!galleryProvider.getControlsVisible());
});
},
onHorizontalDragUpdate: (details) {
_onScrubbing(details);
},
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
setState(() {
isVisible = true;
galleryProvider
.setControlsVisible(!galleryProvider.getControlsVisible());
});
}
},
child: Stack(
children: [
Center(
child: GestureDetector(
onTap: () {
setState(() {
galleryProvider.setControlsVisible(
!galleryProvider.getControlsVisible());
});
},
child: AbsorbPointer(
child: VlcPlayer(
controller: _videoPlayerController,
aspectRatio: _videoPlayerController.value.aspectRatio,
placeholder:
const Center(child: CupertinoActivityIndicator()),
},
onHorizontalDragUpdate: (details) {
_onScrubbing(details);
},
child: VisibilityDetector(
key: ObjectKey(widget.video),
onVisibilityChanged: (visibility) {
if (visibility.visibleFraction < 0.5 &&
mounted &&
_videoPlayerController.value.isInitialized) {
_videoPlayerController.pause();

setState(() {
isVisible = false;
});
}
if (visibility.visibleFraction > 0.5 &&
mounted &&
_videoPlayerController.value.isInitialized) {
_videoPlayerController.play();

setState(() {
isVisible = true;
});
}
},
child: Stack(
children: [
Center(
child: AbsorbPointer(
child: VlcPlayer(
controller: _videoPlayerController,
aspectRatio: _videoPlayerController.value.aspectRatio,
placeholder:
const Center(child: CupertinoActivityIndicator()),
),
),
),
),
),
Opacity(
opacity: galleryProvider.getControlsVisible() ? 1 : 0,
child: SafeArea(
child: Column(
children: [
Expanded(
child: Container(),
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 5),
height: 45,
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(15),
// The BackdropFilter is currently bugged in flutter, it will not cut the border radius
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 10.0, sigmaY: 10.0),
child: Container(
decoration: const BoxDecoration(
color: Color.fromRGBO(50, 50, 50, 0.50),
borderRadius: BorderRadius.all(
Radius.circular(15))),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
Opacity(
opacity: galleryProvider.getControlsVisible() ? 1 : 0,
child: SafeArea(
child: Column(
children: [
Expanded(
child: Container(),
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 5),
height: 45,
child: Stack(
children: [
IconButton(
color: Colors.white,
icon: _videoPlayerController.value.isPlaying
? const Icon(Icons.pause)
: const Icon(Icons.play_arrow),
onPressed: _togglePlaying,
ClipRRect(
borderRadius: BorderRadius.circular(15),
// The BackdropFilter is currently bugged in flutter, it will not cut the border radius
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 10.0, sigmaY: 10.0),
child: Container(
decoration: const BoxDecoration(
color:
Color.fromRGBO(50, 50, 50, 0.50),
borderRadius: BorderRadius.all(
Radius.circular(15))),
),
),
),
Expanded(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
Text(
position,
style: const TextStyle(
color: Colors.white,
fontSize: 12,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
color: Colors.white,
icon:
_videoPlayerController.value.isPlaying
? const Icon(Icons.pause)
: const Icon(Icons.play_arrow),
onPressed: _togglePlaying,
),
Expanded(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
Text(
position,
style: const TextStyle(
color: Colors.white,
fontSize: 12,
),
),
Expanded(
child: Slider(
activeColor:
CupertinoColors.systemGrey,
inactiveColor:
CupertinoColors.systemFill,
thumbColor: CupertinoColors.white,
value: sliderValue,
min: 0.0,
max: (!validPosition &&
_videoPlayerController
.value.duration ==
null)
? 1.0
: _videoPlayerController
.value.duration.inSeconds
.toDouble(),
onChanged: validPosition
? _onSliderPositionChanged
: null,
),
),
Text(
duration,
style: const TextStyle(
color: Colors.white,
fontSize: 12,
),
),
const SizedBox(
width: 15,
)
],
),
Expanded(
child: Slider(
activeColor:
CupertinoColors.systemGrey,
inactiveColor:
CupertinoColors.systemFill,
thumbColor: CupertinoColors.white,
value: sliderValue,
min: 0.0,
max: (!validPosition &&
_videoPlayerController
.value.duration ==
null)
? 1.0
: _videoPlayerController
.value.duration.inSeconds
.toDouble(),
onChanged: validPosition
? _onSliderPositionChanged
: null,
),
),
Text(
duration,
style: const TextStyle(
color: Colors.white,
fontSize: 12,
),
),
const SizedBox(
width: 15,
)
],
),
),
],
),
],
),
],
),
),
],
),
],
),
),
),
],
),
],
),
),
),
],
Expand Down
1 change: 0 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ dependencies:
flutter_launcher_icons: ^0.14.1
shared_preferences: ^2.2.3
visibility_detector: ^0.4.0+2
preload_page_view: ^0.2.0
share_plus: ^7.2.2
url_launcher: ^6.3.0
provider: ^6.1.2
Expand Down

0 comments on commit 25ce86c

Please sign in to comment.