import QtQuick 6.8 import QtMultimedia 6.8 import QtQuick.Controls 6.8 import QtQuick.Layouts 6.8 import QYRComponents 1.0 Item { // color: Colors.surface1 // radius: 10 required property string id property bool hasThumbnail: false property bool loading: true property bool failed: false property string title property string description property string extension property real position: 0 property real duration: 0 property real ratio anchors.fill: parent ColumnLayout { visible: !loading && !failed anchors.fill: parent Image { Layout.fillWidth: true height: width * parent.parent.ratio asynchronous: true cache: true source: parent.parent.hasThumbnail ? ("https://youvideo.nonamesoft.xyz/thumbnails/" + parent.parent.id) : "https://youvideo.nonamesoft.xyz/thumbnails/audio.png" fillMode: Image.PreserveAspectFit } RowLayout { Button { text: Player.loading ? "Loading" : (Player.playing ? "Pause" : "Play") enabled: !Player.loading onClicked: function() { if (Player.playing) { Player.pause() } else { Player.play(); } } } Button { text: "Stop" onClicked: Player.stop() } Label { heading: "h4" text: new Date(Player.position).toISOString().slice(14, 19) } Slider { Layout.fillWidth: true from: 0 to: parent.parent.parent.duration value: parent.parent.parent.position buffered: Player.buffered onMoved: Player.position = value } Label { heading: "h4" text: new Date(parent.parent.parent.duration).toISOString().slice(14, 19) } Label { text: Player.buffered } Slider { from: 0 to: 1 value: Player.volume onMoved: Player.volume = value } } Label { Layout.fillWidth: true wrapMode: Text.WordWrap clip: true text: parent.parent.title heading: "h2" font.bold: true } Label { Layout.fillWidth: true wrapMode: Text.WordWrap clip: true text: parent.parent.description heading: "h4" font.bold: true } Item { Layout.fillHeight: true } } BusyIndicator { anchors.centerIn: parent visible: loading running: loading } ColumnLayout { Layout.alignment: Qt.AlignVCenter anchors.centerIn: parent visible: failed Label { text: "Couldn't get video details!" heading: "h2" font.bold: true } Label { text: "This could mean that either your internet or YouVideo is down." heading: "h4" } Label { Layout.bottomMargin: 25 text: "Check your network connection and try again!" heading: "h4" } Button { text: "Retry" onClicked: parent.fetchData() } } Timer { interval: 1000 running: true onTriggered: parent.fetchData() } function fetchData() { loading = true; failed = false; const xhr = new XMLHttpRequest; xhr.open("GET", "https://youvideo.nonamesoft.xyz/youvideo/video/" + id); xhr.onreadystatechange = function() { if (xhr.readyState == XMLHttpRequest.DONE) { loading = false; if (xhr.status != 200) { console.log("Invalid response"); failed = true; return; } const data = JSON.parse(xhr.responseText); console.log("Received video metadata"); title = data.name; description = data.description; extension = data.extension; ratio = data.metadata.size[0] / data.metadata.size[1]; console.log(ratio); } } xhr.ontimeout = function() { loading = false; failed = true; console.log("Request timed out"); } xhr.send(); } }