Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
590a219f22 | ||
|
|
e68ff6d01c | ||
|
|
d5fcee258e |
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -22,14 +22,12 @@ Item {
|
||||
required property var info // VideoInfoExtractor object
|
||||
required property var audio // Audio object
|
||||
|
||||
readonly property bool isWidescreen: width >= Kirigami.Units.gridUnit * 40
|
||||
|
||||
readonly property bool isWidescreen: width >= Kirigami.Units.gridUnit * 50
|
||||
signal requestOpen()
|
||||
|
||||
Rectangle {
|
||||
id: miniProgressBar
|
||||
z: 1
|
||||
visible: !root.isWidescreen
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
height: root.progressBarHeight
|
||||
@@ -38,14 +36,14 @@ Item {
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
width: !isWidescreen? root.width- controlButtonBox.width: root.width
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: Kirigami.Units.gridUnit * 20
|
||||
Layout.preferredWidth: Kirigami.Units.gridUnit * 20
|
||||
|
||||
color: Qt.rgba(0, 0, 0, trackClick.containsMouse ? 0.1 : trackClick.pressed ? 0.3 : 0)
|
||||
|
||||
RowLayout {
|
||||
@@ -78,10 +76,12 @@ Item {
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// track information
|
||||
ColumnLayout {
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
@@ -92,6 +92,7 @@ Item {
|
||||
wrapMode: Text.Wrap
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: Kirigami.Units.gridUnit * 15
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
@@ -112,14 +113,16 @@ Item {
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
Layout.maximumWidth: Kirigami.Units.gridUnit * 15
|
||||
// Hardcoded because the footerbar blur always makes a dark-ish
|
||||
// background, so we don't want to use a color scheme color that
|
||||
// might also be dark
|
||||
color: "white"
|
||||
}
|
||||
}
|
||||
Item{Layout.fillWidth: true}
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: trackClick
|
||||
anchors.fill: parent
|
||||
@@ -127,85 +130,162 @@ Item {
|
||||
onClicked: root.requestOpen()
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
visible: root.isWidescreen
|
||||
Layout.preferredWidth: 0
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
Label {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
color: "white"
|
||||
visible: info.title
|
||||
text: PlayerUtils.formatTimestamp(audio.position)
|
||||
}
|
||||
}
|
||||
|
||||
Slider {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: audio.duration
|
||||
value: audio.position
|
||||
enabled: audio.seekable
|
||||
onMoved: {
|
||||
console.log("Value:", value);
|
||||
audio.seek(Math.floor(value));
|
||||
}
|
||||
RowLayout {
|
||||
id: controlButtonBox
|
||||
anchors.centerIn: isWidescreen? root:null
|
||||
anchors.right: !isWidescreen? root.right:null
|
||||
Layout.fillHeight: true
|
||||
spacing: 2
|
||||
|
||||
Behavior on value {
|
||||
NumberAnimation {
|
||||
duration: 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
color: "white"
|
||||
visible: info.title
|
||||
text: PlayerUtils.formatTimestamp(audio.duration)
|
||||
}
|
||||
Label {
|
||||
color: "white"
|
||||
visible: info.title && root.isWidescreen
|
||||
text: PlayerUtils.formatTimestamp(audio.position)
|
||||
Layout.rightMargin: 20
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: playPauseButton
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 3
|
||||
Layout.maximumWidth: height
|
||||
Layout.preferredWidth: height
|
||||
|
||||
enabled: info.audioUrl != ""
|
||||
onClicked: audio.playbackState === Audio.PlayingState ? audio.pause() : audio.play()
|
||||
|
||||
icon.name: audio.playbackState === Audio.PlayingState ? "media-playback-pause" : "media-playback-start"
|
||||
icon.width: Kirigami.Units.gridUnit
|
||||
icon.height: Kirigami.Units.gridUnit
|
||||
icon.color: "white"
|
||||
|
||||
Button {
|
||||
id: skipBackwardButton
|
||||
height: 40
|
||||
width: 40
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
|
||||
enabled: UserPlaylistModel.canSkipBack
|
||||
onClicked: UserPlaylistModel.previous()
|
||||
contentItem: Item{
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn:parent
|
||||
source:"media-skip-backward"
|
||||
color: "white"
|
||||
width: Kirigami.Units.gridUnit
|
||||
height: Kirigami.Units.gridUnit
|
||||
|
||||
}
|
||||
}
|
||||
background: Kirigami.ShadowedRectangle{
|
||||
corners.topLeftRadius: 7
|
||||
corners.bottomLeftRadius: 7
|
||||
|
||||
|
||||
color: if (isWidescreen){
|
||||
if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
Qt.rgba(1, 1, 1, 0.2)
|
||||
}
|
||||
} else {
|
||||
if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
"transparent"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
|
||||
Button {
|
||||
id: playPauseButton
|
||||
height: 40
|
||||
width: 60
|
||||
onClicked: audio.playbackState === Audio.PlayingState ? audio.pause() : audio.play()
|
||||
contentItem: Item{
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn:parent
|
||||
source: audio.playbackState === Audio.PlayingState ? "media-playback-pause" : "media-playback-start"
|
||||
color: "white"
|
||||
width: Kirigami.Units.gridUnit
|
||||
height: Kirigami.Units.gridUnit
|
||||
}
|
||||
}
|
||||
background: Kirigami.ShadowedRectangle{
|
||||
color: if (isWidescreen){
|
||||
if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
Qt.rgba(1, 1, 1, 0.2)
|
||||
}
|
||||
} else {
|
||||
if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
"transparent"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Button {
|
||||
id: skipForwardButton
|
||||
Layout.rightMargin: Math.floor(Kirigami.Units.smallSpacing / 2)
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 3
|
||||
Layout.maximumWidth: height
|
||||
Layout.preferredWidth: height
|
||||
|
||||
height: 40
|
||||
width: 40
|
||||
Layout.rightMargin:isWidescreen?0:10
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
|
||||
enabled: UserPlaylistModel.canSkip
|
||||
onClicked: UserPlaylistModel.next()
|
||||
|
||||
icon.name: "media-skip-forward"
|
||||
icon.width: Kirigami.Units.gridUnit
|
||||
icon.height: Kirigami.Units.gridUnit
|
||||
icon.color: "white"
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
contentItem: Item{
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn:parent
|
||||
source:"media-skip-forward"
|
||||
color: "white"
|
||||
width: Kirigami.Units.gridUnit
|
||||
height: Kirigami.Units.gridUnit
|
||||
|
||||
}
|
||||
}
|
||||
background: Kirigami.ShadowedRectangle{
|
||||
corners.topRightRadius: 7
|
||||
corners.bottomRightRadius: 7
|
||||
color: if (isWidescreen){
|
||||
if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
Qt.rgba(1, 1, 1, 0.2)
|
||||
}
|
||||
} else {
|
||||
if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
"transparent"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Label {
|
||||
color: "white"
|
||||
visible: info.title && root.isWidescreen
|
||||
text: PlayerUtils.formatTimestamp(audio.duration)
|
||||
Layout.leftMargin: 20
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,7 @@ Flickable {
|
||||
property int footerSpacing:0
|
||||
property bool maximized: false
|
||||
|
||||
readonly property int progressBarHeight: Kirigami.Units.gridUnit / 6
|
||||
readonly property int progressBarHeight: Kirigami.Units.gridUnit / 4
|
||||
readonly property int minimizedPlayerContentHeight: Math.round(Kirigami.Units.gridUnit * 3.5)
|
||||
readonly property int minimizedPlayerHeight: minimizedPlayerContentHeight + progressBarHeight
|
||||
|
||||
@@ -158,8 +158,8 @@ Flickable {
|
||||
layer.effect: HueSaturation {
|
||||
cached: true
|
||||
|
||||
lightness: -0.5
|
||||
saturation: 1.9
|
||||
lightness: -0.7
|
||||
saturation: 3
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: FastBlur {
|
||||
|
||||
@@ -224,6 +224,8 @@ Item {
|
||||
|
||||
Controls.ScrollView {
|
||||
id: mainScrollView
|
||||
|
||||
clip: true
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -129,6 +129,20 @@ QString UserPlaylistModel::nextVideoId() const
|
||||
return QString::fromStdString((currentTrack + 1)->video_id);
|
||||
}
|
||||
|
||||
QString UserPlaylistModel::previousVideoId() const
|
||||
{
|
||||
auto currentTrack = std::find_if(m_playlist.tracks.begin(), m_playlist.tracks.end(),
|
||||
[this](const watch::Playlist::Track &track) {
|
||||
return track.video_id == m_currentVideoId.toStdString();
|
||||
});
|
||||
|
||||
if (currentTrack == m_playlist.tracks.end() || currentTrack - 1 == m_playlist.tracks.end()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return QString::fromStdString((currentTrack - 1)->video_id);
|
||||
}
|
||||
|
||||
QString UserPlaylistModel::currentVideoId() const
|
||||
{
|
||||
return m_currentVideoId;
|
||||
@@ -141,6 +155,8 @@ void UserPlaylistModel::setCurrentVideoId(const QString &videoId)
|
||||
emitCurrentVideoChanged(old);
|
||||
Q_EMIT currentVideoIdChanged();
|
||||
Q_EMIT canSkipChanged();
|
||||
Q_EMIT canSkipBackChanged();
|
||||
|
||||
}
|
||||
|
||||
int UserPlaylistModel::currentIndex() const
|
||||
@@ -164,12 +180,32 @@ bool UserPlaylistModel::canSkip() const
|
||||
&& currentTrackIt != m_playlist.tracks.end()
|
||||
&& !m_playlist.tracks.empty();
|
||||
}
|
||||
bool UserPlaylistModel::canSkipBack() const
|
||||
{
|
||||
const auto currentTrackIt = std::ranges::find_if(m_playlist.tracks, [this](const watch::Playlist::Track &track) {
|
||||
return track.video_id == m_currentVideoId.toStdString();
|
||||
});
|
||||
|
||||
return currentTrackIt != m_playlist.tracks.begin()
|
||||
&& !m_playlist.tracks.empty();
|
||||
}
|
||||
|
||||
void UserPlaylistModel::next()
|
||||
{
|
||||
setCurrentVideoId(nextVideoId());
|
||||
Q_EMIT currentVideoIdChanged();
|
||||
Q_EMIT canSkipChanged();
|
||||
Q_EMIT canSkipBackChanged();
|
||||
|
||||
}
|
||||
|
||||
void UserPlaylistModel::previous()
|
||||
{
|
||||
setCurrentVideoId(previousVideoId());
|
||||
Q_EMIT currentVideoIdChanged();
|
||||
Q_EMIT canSkipChanged();
|
||||
Q_EMIT canSkipBackChanged();
|
||||
|
||||
}
|
||||
|
||||
void UserPlaylistModel::skipTo(const QString &videoId)
|
||||
@@ -179,6 +215,8 @@ void UserPlaylistModel::skipTo(const QString &videoId)
|
||||
emitCurrentVideoChanged(old);
|
||||
Q_EMIT currentVideoIdChanged();
|
||||
Q_EMIT canSkipChanged();
|
||||
Q_EMIT canSkipBackChanged();
|
||||
|
||||
}
|
||||
|
||||
void UserPlaylistModel::playNext(const QString &videoId, const QString &title, const std::vector<meta::Artist> &artists)
|
||||
@@ -199,6 +237,8 @@ void UserPlaylistModel::playNext(const QString &videoId, const QString &title, c
|
||||
endInsertRows();
|
||||
setCurrentVideoId(videoId);
|
||||
Q_EMIT canSkipChanged();
|
||||
Q_EMIT canSkipBackChanged();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -208,6 +248,8 @@ void UserPlaylistModel::playNext(const QString &videoId, const QString &title, c
|
||||
m_playlist.tracks.push_back(std::move(track));
|
||||
endInsertRows();
|
||||
Q_EMIT canSkipChanged();
|
||||
Q_EMIT canSkipBackChanged();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -216,6 +258,8 @@ void UserPlaylistModel::playNext(const QString &videoId, const QString &title, c
|
||||
m_playlist.tracks.insert(currentIt + 1, std::move(track));
|
||||
endInsertRows();
|
||||
Q_EMIT canSkipChanged();
|
||||
Q_EMIT canSkipBackChanged();
|
||||
|
||||
}
|
||||
|
||||
void UserPlaylistModel::append(const QString &videoId, const QString &title, const std::vector<meta::Artist> &artists)
|
||||
@@ -242,6 +286,8 @@ void UserPlaylistModel::clear()
|
||||
|
||||
setCurrentVideoId({});
|
||||
Q_EMIT canSkipChanged();
|
||||
Q_EMIT canSkipBackChanged();
|
||||
|
||||
}
|
||||
|
||||
void UserPlaylistModel::remove(const QString &videoId)
|
||||
@@ -259,6 +305,8 @@ void UserPlaylistModel::remove(const QString &videoId)
|
||||
endRemoveRows();
|
||||
|
||||
Q_EMIT canSkipChanged();
|
||||
Q_EMIT canSkipBackChanged();
|
||||
|
||||
}
|
||||
|
||||
void UserPlaylistModel::shufflePlaylist()
|
||||
|
||||
@@ -23,6 +23,7 @@ class UserPlaylistModel : public AbstractYTMusicModel
|
||||
Q_PROPERTY(QString currentVideoId READ currentVideoId NOTIFY currentVideoIdChanged)
|
||||
Q_PROPERTY(int currentIndex READ currentIndex NOTIFY currentVideoIdChanged)
|
||||
Q_PROPERTY(bool canSkip READ canSkip NOTIFY canSkipChanged)
|
||||
Q_PROPERTY(bool canSkipBack READ canSkipBack NOTIFY canSkipBackChanged)
|
||||
Q_PROPERTY(QString lyrics READ lyrics NOTIFY lyricsChanged)
|
||||
|
||||
public:
|
||||
@@ -46,6 +47,7 @@ public:
|
||||
Q_SIGNAL void initialVideoIdChanged();
|
||||
|
||||
QString nextVideoId() const;
|
||||
QString previousVideoId() const;
|
||||
|
||||
QString currentVideoId() const;
|
||||
void setCurrentVideoId(const QString &videoId);
|
||||
@@ -54,7 +56,11 @@ public:
|
||||
int currentIndex() const;
|
||||
|
||||
bool canSkip() const;
|
||||
bool canSkipBack() const;
|
||||
|
||||
Q_SIGNAL void canSkipChanged();
|
||||
Q_SIGNAL void canSkipBackChanged();
|
||||
|
||||
|
||||
QString playlistId() const;
|
||||
void setPlaylistId(const QString &playlistId);
|
||||
@@ -68,6 +74,8 @@ public:
|
||||
Q_SIGNAL void lyricsChanged();
|
||||
|
||||
Q_INVOKABLE void next();
|
||||
Q_INVOKABLE void previous();
|
||||
|
||||
Q_INVOKABLE void skipTo(const QString &videoId);
|
||||
Q_INVOKABLE void playNext(const QString &videoId, const QString &title, const std::vector<meta::Artist> &artists);
|
||||
Q_INVOKABLE void append(const QString &videoId, const QString &title, const std::vector<meta::Artist> &artists);
|
||||
|
||||
Reference in new issue
Block a user