Skip to content

Commit

Permalink
fix issue with playlist performance when there are a lot of videos
Browse files Browse the repository at this point in the history
add handling of remote media buttons (play/pause/skip etc...)
add exponentially increasing fast forward / rewind if the remote is pressed rapidly or held for long

fix #247
fix #257
  • Loading branch information
lamarios committed Aug 1, 2023
1 parent 748ecf3 commit fce393c
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 86 deletions.
17 changes: 17 additions & 0 deletions lib/controllers/tvChannelController.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@ import 'package:invidious/globals.dart';

class TvChannelController extends ChannelController {
final ScrollController scrollController = ScrollController();
bool showBackground = false;

TvChannelController(super.channelId);

@override
Future<void> onReady() async {
super.onReady();
scrollController.addListener(onScroll);
}

@override
void onClose() {
scrollController.dispose();
Expand All @@ -18,4 +25,14 @@ class TvChannelController extends ChannelController {
scrollController.animateTo(0, duration: animationDuration ~/ 2, curve: Curves.easeInOutQuad);
}
}

void onScroll() {
if (scrollController.offset == 0) {
showBackground = false;
update();
} else if (!showBackground) {
showBackground = true;
update();
}
}
}
61 changes: 55 additions & 6 deletions lib/controllers/tvPlayerController.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import '../utils.dart';
const Duration controlFadeOut = Duration(seconds: 4);
const Duration throttleDuration = Duration(milliseconds: 250);

const defaultStep = 10;
const stepMultiplier = 0.2;

class TvPlayerController extends GetxController {
Logger log = Logger('TvPlayerController');

Expand All @@ -31,6 +34,7 @@ class TvPlayerController extends GetxController {
bool showQueue = false;
bool showControls = false;
late Video currentlyPlaying;
int forwardStep = defaultStep, rewindStep = defaultStep;

Duration get videoLength => Duration(seconds: PlayerController.to()?.video?.lengthSeconds ?? 0);

Expand All @@ -39,15 +43,23 @@ class TvPlayerController extends GetxController {
togglePlayPause() {
showUi();
if (isPlaying) {
log.info('Pausing video');
PlayerController.to()?.videoController?.pause();
pause();
} else {
log.info('Playing video');
PlayerController.to()?.videoController?.play();
play();
}
update();
}

play() {
log.info('Playing video');
PlayerController.to()?.videoController?.play();
}

pause() {
log.info('Pausing video');
PlayerController.to()?.videoController?.pause();
}

@override
void onReady() async {
currentlyPlaying = await service.getVideo(videos[0].videoId);
Expand Down Expand Up @@ -114,11 +126,19 @@ class TvPlayerController extends GetxController {
}

fastForward() {
PlayerController.to()?.videoController?.seekTo(currentPosition + const Duration(seconds: 10));
PlayerController.to()?.videoController?.seekTo(currentPosition + Duration(seconds: forwardStep));
forwardStep += (forwardStep * stepMultiplier).floor();
EasyDebounce.debounce('fast-forward-step', const Duration(seconds: 1), () {
forwardStep = defaultStep;
});
}

fastRewind() {
PlayerController.to()?.videoController?.seekTo(currentPosition - const Duration(seconds: 10));
PlayerController.to()?.videoController?.seekTo(currentPosition - Duration(seconds: rewindStep));
rewindStep += (rewindStep * stepMultiplier).floor();
EasyDebounce.debounce('fast-rewind-step', const Duration(seconds: 1), () {
rewindStep = defaultStep;
});
}

playNext() async {
Expand Down Expand Up @@ -185,6 +205,35 @@ class TvPlayerController extends GetxController {
update();
return KeyEventResult.handled;
} else if (event is KeyUpEvent) {
switch (event.logicalKey) {
case LogicalKeyboardKey.mediaPlay:
play();
break;
case LogicalKeyboardKey.mediaPause:
pause();
break;
case LogicalKeyboardKey.mediaPlayPause:
togglePlayPause();
break;

case LogicalKeyboardKey.mediaFastForward:
case LogicalKeyboardKey.mediaStepForward:
case LogicalKeyboardKey.mediaSkipForward:
fastForward();
break;
case LogicalKeyboardKey.mediaRewind:
case LogicalKeyboardKey.mediaStepBackward:
case LogicalKeyboardKey.mediaSkipBackward:
fastRewind();
break;
case LogicalKeyboardKey.mediaTrackNext:
playNext();
break;
case LogicalKeyboardKey.mediaTrackPrevious:
playPrevious();
break;
}

if (timeLineControl) {
if (event.logicalKey == LogicalKeyboardKey.arrowRight) {
fastForward();
Expand Down
25 changes: 25 additions & 0 deletions lib/controllers/tvPlaylistController.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:invidious/controllers/playlistController.dart';

class TvPlaylistController extends PlaylistController {
bool miniTop = false;

@override
onReady() {
super.onReady();
scrollController.addListener(onScroll);
}

TvPlaylistController({required super.playlist, required super.playlistItemHeight});
void setMiniTop(bool bool) {
miniTop = bool;
update();
}

void onScroll() {
if (scrollController.offset == 0) {
setMiniTop(false);
} else if (!miniTop) {
setMiniTop(true);
}
}
}
48 changes: 26 additions & 22 deletions lib/views/tv/tvChannelView.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,30 +42,34 @@ class TvChannelView extends StatelessWidget {
child: Stack(
children: [
Positioned(top: 0, left: 0, right: 0, child: CachedNetworkImage(imageUrl: ImageObject.getBestThumbnail(_.channel?.authorBanners)?.url ?? '')),
TvOverscan(
child: Padding(
padding: const EdgeInsets.only(top: 100),
AnimatedContainer(
color: _.showBackground ? colors.background.withOpacity(0.5) : colors.background.withOpacity(0),
duration: animationDuration,
child: TvOverscan(
child: ListView(controller: _.scrollController, children: [
Align(
alignment: Alignment.centerLeft,
child: Container(
decoration: BoxDecoration(color: colors.background.withOpacity(1), borderRadius: BorderRadius.circular(35)),
child: Row(mainAxisSize: MainAxisSize.min, children: [
Thumbnail(
thumbnailUrl: ImageObject.getBestThumbnail(_.channel?.authorThumbnails)?.url ?? '',
width: 70,
height: 70,
id: 'author-big-${_.channel?.authorId}',
decoration: BoxDecoration(borderRadius: BorderRadius.circular(35)),
),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 20),
child: Text(
_.channel?.author ?? '',
style: textTheme.displaySmall,
Padding(
padding: const EdgeInsets.only(top: 100.0),
child: Align(
alignment: Alignment.centerLeft,
child: Container(
decoration: BoxDecoration(color: colors.background.withOpacity(1), borderRadius: BorderRadius.circular(35)),
child: Row(mainAxisSize: MainAxisSize.min, children: [
Thumbnail(
thumbnailUrl: ImageObject.getBestThumbnail(_.channel?.authorThumbnails)?.url ?? '',
width: 70,
height: 70,
id: 'author-big-${_.channel?.authorId}',
decoration: BoxDecoration(borderRadius: BorderRadius.circular(35)),
),
)
]),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 20),
child: Text(
_.channel?.author ?? '',
style: textTheme.displaySmall,
),
)
]),
),
),
),
TvSubscribeButton(
Expand Down
2 changes: 1 addition & 1 deletion lib/views/tv/tvPlayerView.dart
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class TvPlayerView extends StatelessWidget {
left: 0,
right: 0,
child: _.showSettings
? SizedBox.shrink()
? const SizedBox.shrink()
: AnimatedOpacity(
opacity: _.controlsOpacity,
duration: animationDuration,
Expand Down
Loading

0 comments on commit fce393c

Please sign in to comment.