Skip to content

Commit

Permalink
chore: ui fixes
Browse files Browse the repository at this point in the history
- duration not refreshing in miniplayer if required
- yt miniplayer not having proper padding initially
- video quality menu around whole tile in dl options dialog
- show more format info in local miniplayer video streams
- displaying that audio is cached even tho cache list is empty
  • Loading branch information
MSOB7YY committed Nov 21, 2024
1 parent ac8505d commit 5c14e30
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 55 deletions.
2 changes: 1 addition & 1 deletion lib/controller/video_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ class VideoController {
creationTimeMS: stats.creationDate.millisecondsSinceEpoch,
frameratePrecise: frameratePrecise ?? 0.0,
durationMS: videoStream?.duration?.inMilliseconds ?? mediaInfo?.format?.duration?.inMilliseconds ?? 0,
bitrate: int.tryParse(videoStream?.bitRate ?? '') ?? 0,
bitrate: int.tryParse(videoStream?.bitRate ?? mediaInfo?.format?.bitRate ?? '') ?? 0,
);
}

Expand Down
17 changes: 11 additions & 6 deletions lib/packages/miniplayer_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ class _NamidaMiniPlayerBaseState extends State<NamidaMiniPlayerBase> {
final prevItem = queue.isEmpty ? null : queue[indminus];
final currentItem = queue[currentIndex];
final nextItem = queue.isEmpty ? null : queue[indplus];
final currentDurationInMS = Player.inst.currentItemDuration.valueR?.inMilliseconds ?? widget.getDurationMS?.call(currentItem) ?? 0;
final currentDefaultDurationInMS = widget.getDurationMS?.call(currentItem) ?? 0;

final prevText = prevItem == null ? null : widget.textBuilder(prevItem);
final currentText = widget.textBuilder(currentItem);
Expand Down Expand Up @@ -501,6 +501,7 @@ class _NamidaMiniPlayerBaseState extends State<NamidaMiniPlayerBase> {
toSubtract = Player.inst.nowPlayingPositionR;
prefix = '-';
}
final currentDurationInMS = currentDefaultDurationInMS > 0 ? currentDefaultDurationInMS : Player.inst.currentItemDuration.valueR?.inMilliseconds ?? 0;
final msToDisplay = currentDurationInMS - toSubtract;
return Text(
"$prefix ${msToDisplay.milliSecondsLabel}",
Expand Down Expand Up @@ -593,12 +594,14 @@ class _NamidaMiniPlayerBaseState extends State<NamidaMiniPlayerBase> {
final currentId = focusedMenuOptions.currentId(currentItem);
final cacheFile = currentId == null ? null : element.getCachedFile(currentId);
final cacheExists = cacheFile != null;
var codecIdentifier = element.codecInfo.codecIdentifierIfCustom();
var codecIdentifierText = codecIdentifier != null ? ' (${codecIdentifier.toUpperCase()})' : '';
return _MPQualityButton(
onTap: () => focusedMenuOptions.onStreamVideoTap(currentItem, currentId, element, cacheFile, focusedMenuOptions.streams.value),
bgColor: cacheExists ? CurrentColor.inst.miniplayerColor.withAlpha(40) : null,
icon: cacheExists ? Broken.tick_circle : Broken.import,
title: "${element.qualityLabel} • ${element.sizeInBytes.fileSizeFormatted}",
subtitle: "${element.codecInfo.container} • ${element.bitrateText()}",
subtitle: "${element.codecInfo.container} • ${element.bitrateText()}$codecIdentifierText",
);
},
),
Expand Down Expand Up @@ -803,10 +806,12 @@ class _NamidaMiniPlayerBaseState extends State<NamidaMiniPlayerBase> {
),

/// Smol progress bar
ObxO(
rx: Player.inst.nowPlayingPosition,
builder: (context, nowPlayingPosition) {
final w = currentDurationInMS == 0 ? 0 : nowPlayingPosition / currentDurationInMS;
Obx(
(context) {
final nowPlayingPosition = Player.inst.nowPlayingPosition.valueR;
final currentDurationInMS =
currentDefaultDurationInMS > 0 ? currentDefaultDurationInMS : Player.inst.currentItemDuration.valueR?.inMilliseconds ?? 0;
final w = currentDurationInMS > 0 ? nowPlayingPosition / currentDurationInMS : 0;
return Container(
height: 2 * (1 - cp),
width: w > 0 ? ((context.width * w) * 0.9) : 0,
Expand Down
23 changes: 14 additions & 9 deletions lib/packages/mp.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:flutter/material.dart';

import 'package:namida/controller/wakelock_controller.dart';
Expand Down Expand Up @@ -75,6 +77,18 @@ class NamidaYTMiniplayerState extends State<NamidaYTMiniplayer> with SingleTicke
_dragheight = _wasExpanded ? _maxHeight : widget.minHeight;

WakelockController.inst.updateMiniplayerStatus(_wasExpanded);

Timer(
Duration(milliseconds: 1000),
() {
// -- context access in build makes it awful for yt miniplayer (since it has MaterialPage),
// -- the keyboard keeps showing/hiding
// -- so yeah we only check once
final padding = MediaQuery.paddingOf(context);
_padding = padding;
animateToState(_wasExpanded);
},
);
}

void _listenerHeightChange() {
Expand Down Expand Up @@ -194,15 +208,6 @@ class NamidaYTMiniplayerState extends State<NamidaYTMiniplayer> with SingleTicke

@override
Widget build(BuildContext context) {
if (_padding == EdgeInsets.zero) {
// -- context access makes it awful for yt miniplayer (since it has MaterialPage),
// -- the keyboard keeps showing/hiding
// -- so yeah we only check once
final padding = MediaQuery.paddingOf(context);
_padding = padding;
animateToState(_wasExpanded);
}

final maxWidth = context.width;
return AnimatedBuilder(
animation: controller,
Expand Down
9 changes: 7 additions & 2 deletions lib/ui/widgets/video_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ class NamidaVideoControlsState extends State<NamidaVideoControls> with TickerPro
cachedQualities.removeWhere(
(cq) {
return ytQualities.any((ytq) {
if (widget.isLocal) return ytq.height == cq.height;
if (widget.isLocal) return ytq.height == cq.height && ytq.bitrate == cq.bitrate;
final cachePath = videoId == null ? null : ytq.cachePath(videoId);
if (cachePath == cq.path) return true;
if (ytq.sizeInBytes == cq.sizeInBytes) return true;
Expand Down Expand Up @@ -1153,11 +1153,16 @@ class NamidaVideoControlsState extends State<NamidaVideoControls> with TickerPro
(context) {
if (widget.isLocal) {
final id = Player.inst.currentVideoR?.id;
final isSelected = element.height == VideoController.inst.currentVideo.valueR?.height;
final selectedVideo = VideoController.inst.currentVideo.valueR;
final isSelected = element.height == selectedVideo?.height && element.bitrate == selectedVideo?.bitrate;

var codecIdentifier = element.codecInfo.codecIdentifierIfCustom();
var codecIdentifierText = codecIdentifier != null ? ' (${codecIdentifier.toUpperCase()})' : '';

return _getQualityChip(
title: element.qualityLabel,
subtitle: " • ${element.sizeInBytes.fileSizeFormatted}",
thirdLine: "${element.bitrateText()}$codecIdentifierText",
onPlay: (isSelected) {
if (!isSelected || Player.inst.videoPlayerInfo.value?.isInitialized != true) {
Player.inst.onItemPlayYoutubeIDSetQuality(
Expand Down
72 changes: 37 additions & 35 deletions lib/youtube/pages/yt_playlist_download_subpage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,13 @@ class _YTPlaylistDownloadPageState extends State<YTPlaylistDownloadPage> {
}

void onRenameAllTasks(String? defaultFilename) {
widget.ids.mapIndexed((ytid, originalIndex) => _configMap[ytid.id] = _getDummyDownloadConfig(ytid.id, originalIndex, defaultFilename: defaultFilename)).toList();
widget.ids.mapIndexed((ytid, originalIndex) => _configMap.value[ytid.id] = _getDummyDownloadConfig(ytid.id, originalIndex, defaultFilename: defaultFilename)).toList();
}

void _updateAudioOnly(bool audioOnly) {
settings.save(downloadAudioOnly: audioOnly);
_configMap.entries.toList().loop(
(c) {
_configMap[c.key] = c.value.copyWith(fetchMissingVideo: !audioOnly);
},
);
_configMap.value.updateAll((key, value) => value.copyWith(fetchMissingVideo: !audioOnly));
_configMap.refresh();
}

YoutubeItemDownloadConfig _getDummyDownloadConfig(String id, int originalIndex, {String? defaultFilename}) {
Expand Down Expand Up @@ -129,8 +126,8 @@ class _YTPlaylistDownloadPageState extends State<YTPlaylistDownloadPage> {
required int originalIndex,
}) async {
await showDownloadVideoBottomSheet(
originalIndex: _configMap[id]?.originalIndex,
totalLength: _configMap[id]?.totalLength,
originalIndex: _configMap.value[id]?.originalIndex,
totalLength: _configMap.value[id]?.totalLength,
streamInfoItem: widget.infoLookup[id],
playlistInfo: widget.playlistInfo,
playlistId: widget.playlistInfo?.id,
Expand All @@ -140,7 +137,7 @@ class _YTPlaylistDownloadPageState extends State<YTPlaylistDownloadPage> {
initialItemConfig: _configMap[id],
confirmButtonText: lang.CONFIRM,
onConfirmButtonTap: (groupName, config) {
_configMap[id] = config;
_configMap.value[id] = config;
return true;
},
);
Expand All @@ -149,6 +146,26 @@ class _YTPlaylistDownloadPageState extends State<YTPlaylistDownloadPage> {
void _showAllConfigDialog(BuildContext context) {
const visualDensity = null;

List<NamidaPopupItem> qualityMenuChildren() => [
NamidaPopupItem(
icon: Broken.musicnote,
title: lang.AUDIO,
onTap: () {
_updateAudioOnly(true);
},
),
...kStockVideoQualities.map(
(e) => NamidaPopupItem(
icon: Broken.story,
title: e,
onTap: () {
_updateAudioOnly(false);
preferredQuality.value = e;
},
),
)
];

NamidaNavigator.inst.navigateDialog(
dialog: CustomBlurryDialog(
title: lang.CONFIGURE,
Expand Down Expand Up @@ -239,31 +256,16 @@ class _YTPlaylistDownloadPageState extends State<YTPlaylistDownloadPage> {
onChanged: (isTrue) => settings.save(downloadOverrideOldFiles: !isTrue),
),
),
CustomListTile(
visualDensity: visualDensity,
icon: Broken.story,
title: lang.VIDEO_QUALITY,
trailing: NamidaPopupWrapper(
childrenDefault: () => [
NamidaPopupItem(
icon: Broken.musicnote,
title: lang.AUDIO,
onTap: () {
_updateAudioOnly(true);
},
),
...kStockVideoQualities.map(
(e) => NamidaPopupItem(
icon: Broken.story,
title: e,
onTap: () {
_updateAudioOnly(false);
preferredQuality.value = e;
},
),
)
],
child: Obx((context) => Text(settings.downloadAudioOnly.valueR ? lang.AUDIO_ONLY : preferredQuality.valueR)),
NamidaPopupWrapper(
childrenDefault: qualityMenuChildren,
child: CustomListTile(
visualDensity: visualDensity,
icon: Broken.story,
title: lang.VIDEO_QUALITY,
trailing: NamidaPopupWrapper(
childrenDefault: qualityMenuChildren,
child: Obx((context) => Text(settings.downloadAudioOnly.valueR ? lang.AUDIO_ONLY : preferredQuality.valueR)),
),
),
),
],
Expand Down Expand Up @@ -625,7 +627,7 @@ class _YTPlaylistDownloadPageState extends State<YTPlaylistDownloadPage> {
final itemsConfig = _selectedList.value
.map(
(id) =>
_configMap[id] ??
_configMap.value[id] ??

// -- this is not really used since initState() calls onRenameAllTasks() which fills _configMap
_getDummyDownloadConfig(
Expand Down
2 changes: 1 addition & 1 deletion lib/youtube/yt_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class YTUtils {
Broken.audio_square,
size: 15.0,
color: iconsColor?.withOpacity(
Player.inst.audioCacheMap[videoId] != null || Indexer.inst.allTracksMappedByYTID[videoId] != null ? 0.6 : 0.1,
Player.inst.audioCacheMap[videoId]?.isNotEmpty == true || Indexer.inst.allTracksMappedByYTID[videoId]?.isNotEmpty == true ? 0.6 : 0.1,
),
),
),
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: namida
description: A Beautiful and Feature-rich Music Player, With YouTube & Video Support Built in Flutter
publish_to: "none"
version: 4.7.11-beta+241121221
version: 4.7.14-beta+241121233

environment:
sdk: ">=3.4.0 <4.0.0"
Expand Down

0 comments on commit 5c14e30

Please sign in to comment.