Compare commits

...
8 changed files with 1004 additions and 456 deletions

No files matched your search

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

+1 -1
View File
@@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="48" height="48" version="1.1" viewBox="0 0 12.7 12.7" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="a" x1="25" x2="25" y1="3" y2="42.605" gradientTransform="matrix(.26458 0 0 .26458 5.101e-5 3.6667e-7)" gradientUnits="userSpaceOnUse"><stop stop-color="#f47750" offset="0"/><stop stop-color="#ed1515" offset="1"/></linearGradient><linearGradient id="d" x1="24" x2="24" y1="35.353" y2="12.647" gradientUnits="userSpaceOnUse"><stop stop-color="#31363b" offset="0"/><stop stop-color="#5f6a73" offset="1"/></linearGradient><linearGradient id="c" x1="24" x2="24" y1="29" y2="19" gradientUnits="userSpaceOnUse"><stop stop-color="#4d4d4d" offset="0"/><stop stop-color="#737373" offset="1"/></linearGradient><linearGradient id="b" x1="6.35" x2="6.35" y1="9.525" y2="-1.8372" gradientUnits="userSpaceOnUse"><stop stop-color="#7f8c8d" offset="0"/><stop stop-color="#929d9e" offset="1"/></linearGradient></defs><metadata><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata><g stroke-width=".26458"><rect x="1.0584" y="1.0583" width="10.583" height="10.583" rx="1.5875" ry="1.5875" fill="#a83226" style="paint-order:stroke fill markers"/><rect x="1.0584" y="1.0583" width="10.583" height="10.319" rx="1.5875" ry="1.5875" fill="url(#a)" style="paint-order:stroke fill markers"/><circle cx="6.35" cy="6.35" r="3.175" fill="none" stroke="#eee" stroke-linecap="square" stroke-width=".26458"/><path d="m8.3465 6.35-3.0549 1.7637 3e-7 -1.7637-3e-7 -1.7637 1.5274 0.88187z" fill="#fff"/><path d="m2.3962 5.8208a3.9538 3.9538 0 0 1 3.9538-3.9538 3.9538 3.9538 0 0 1 3.9538 3.9538" fill="none" stroke="url(#b)" stroke-linecap="square" stroke-width=".26458"/><path d="m4.3731 2.3967a3.9538 3.9538 0 0 1 3.9538 1e-7" fill="none" stroke="#6b6b6b" stroke-linecap="round" stroke-width=".52917"/><path transform="scale(.26458)" d="m8 19c-0.554 0-1 0.446-1 1v8c0 0.554 0.446 1 1 1h2c0.554 0 1-0.446 1-1v-8c0-0.554-0.446-1-1-1h-2zm30 0c-0.554 0-1 0.446-1 1v8c0 0.554 0.446 1 1 1h2c0.554 0 1-0.446 1-1v-8c0-0.554-0.446-1-1-1h-2z" fill="url(#c)"/><path transform="scale(.26458)" d="m8 19c-0.554 0-1 0.446-1 1v8c0 0.554 0.446 1 1 1h2v-10h-2zm30 0v10h2c0.554 0 1-0.446 1-1v-8c0-0.554-0.446-1-1-1h-2z" fill="url(#d)"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" width="48" height="48" viewBox="0 0 12.7 12.7"><defs><linearGradient id="c"><stop offset="0" stop-color="#dc8689"/><stop offset="1" stop-color="#d56062"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#da4453"/><stop offset="1" stop-color="#e74c3c"/></linearGradient><linearGradient id="a"><stop offset="0" stop-color="#c0392b"/><stop offset="1" stop-color="#c0392b" stop-opacity="0"/></linearGradient><linearGradient xlink:href="#a" id="e" x1="6.08542" x2="6.08542" y1="6.35" y2="11.3773" gradientUnits="userSpaceOnUse"/><linearGradient xlink:href="#b" id="d" x1="6.61458" x2="6.61458" y1="6.2178" y2="1.0583" gradientTransform="translate(0 -.15143)" gradientUnits="userSpaceOnUse"/><linearGradient xlink:href="#c" id="g" x1="10.58366" x2="11.64167" y1="6.08397" y2="6.08542" gradientUnits="userSpaceOnUse"/><linearGradient xlink:href="#c" id="f" x1="1.05833" x2="2.38125" y1="6.08542" y2="6.08542" gradientTransform="translate(-3.43958)" gradientUnits="userSpaceOnUse"/></defs><rect width="10.583" height="10.583" x="1.0584" y="1.0583" fill="#a83226" paint-order="stroke fill markers" rx="1.5875" ry="1.5875"/><rect width="10.583" height="10.319" x="1.0584" y=".90687" fill="url(#d)" paint-order="stroke fill markers" rx="1.5875" ry="1.5875"/><circle cx="6.35" cy="6.34408" r="3.97467" fill="none" stroke="#a83226" stroke-linecap="square" stroke-width=".51752"/><path fill="url(#e)" d="M1.05885 6.08542v3.83645c0 .87947.70803 1.5875 1.5875 1.5875h7.40782c.87946 0 1.5875-.70803 1.5875-1.5875V6.08542Z" paint-order="stroke fill markers"/><path fill="#ad3327" d="M1.05833 6.08542v.52916h2.51355a.132.132 0 0 0 .13229-.13229v-.26458a.132.132 0 0 0-.1323-.1323H1.05834z"/><path fill="#ac3327" d="M9.6578 6.08542a.132.132 0 0 0-.13228.13229v.26458a.132.132 0 0 0 .13229.1323h1.98386v-.52917Z"/><circle cx="6.3499" cy="6.06637" r="3.97467" fill="none" stroke="#dc8689" stroke-linecap="square" stroke-width=".51752"/><g fill="#ad3327" transform="translate(-.52917 -.26458)"><rect width=".52917" height=".52917" x="4.49792" y="6.35" rx=".13229" ry=".13229"/><rect width=".52917" height="4.7625" x="5.29167" y="4.49792" rx=".13229" ry=".13229"/><rect width=".52917" height="3.70417" x="6.08542" y="5.02708" rx=".13229" ry=".13229"/><rect width=".52917" height="2.64583" x="6.87917" y="5.55625" rx=".13229" ry=".13229"/><rect width=".52917" height="1.5875" x="7.67292" y="6.08542" rx=".13229" ry=".13229"/></g><path fill="#a83226" d="M7.9375 6.489v.27958c0 .06128.059.11059.1323.11059h.26458c.07328 0 .13229-.0493.13229-.1106v-.27956c-.00353.0701-.0613.12557-.1323.12557H8.0698c-.071 0-.12876-.05548-.13229-.12557z"/><path fill="#ad3327" d="M8.73125 6.22443V6.504c0 .06128.059.11058.1323.11058h.26458c.07328 0 .13229-.0493.13229-.11058v-.27957c-.00353.07009-.0613.12557-.1323.12557h-.26458c-.071 0-.12876-.05548-.13229-.12557z"/><rect width=".52917" height=".52917" x="3.96875" y="5.82083" fill="#f0b4ba" rx=".13229" ry=".13229"/><rect width=".52917" height="5.29167" x="4.7625" y="3.43958" fill="#fff" rx=".13229" ry=".13229"/><rect width=".52917" height="4.23333" x="5.55625" y="3.96875" fill="#fff" rx=".13229" ry=".13229"/><rect width=".52917" height="3.175" x="6.35" y="4.49792" fill="#fff" rx=".13229" ry=".13229"/><rect width=".52917" height="2.11667" x="7.14375" y="5.02708" fill="#fff" rx=".13229" ry=".13229"/><rect width=".52917" height="1.05833" x="7.9375" y="5.55625" fill="#fff" rx=".13229" ry=".13229"/><path fill="#dc8689" d="M2.38125 5.82083V6.35h1.19063a.132.132 0 0 0 .13229-.1323v-.26457a.132.132 0 0 0-.1323-.1323z"/><rect width=".52917" height=".52917" x="9.26042" y="6.08542" fill="#f0b4ba" rx=".13229" ry=".13229" transform="translate(-.52917 -.26458)"/><path fill="#dc8689" d="M9.6573 5.82083a.132.132 0 0 0-.1323.1323v.26458a.132.132 0 0 0 .1323.13229h.66145v-.52917Z"/><rect width="1.32292" height=".52917" x="-2.38125" y="5.82083" fill="url(#f)" rx="0" ry="0" transform="scale(-1 1)"/><rect width="1.32292" height=".52917" x="10.31875" y="5.82083" fill="url(#g)" rx="0" ry="0"/></svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

File diff suppressed because it is too large. Load diff
+156 -76
View File
@@ -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
}
}
}
+3 -3
View File
@@ -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 {
+2
View File
@@ -224,6 +224,8 @@ Item {
Controls.ScrollView {
id: mainScrollView
clip: true
Layout.fillHeight: true
Layout.fillWidth: true
+48
View File
@@ -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()
+8
View File
@@ -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);