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 StackView.onRemoved: destroy() 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 Component.onCompleted: Player.onPositionChanged = () => { console.log("test print"); if (Player.id == id) { position = Player.position } } Component.onDestruction: if (Player.id == id) Player.unloadVideo() onPositionChanged: if (Player.id == id) Player.position = position 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.id == id ? (Player.loading ? "Loading" : (Player.playing ? "Pause" : "Play")) : "Play" enabled: Player.id != id || !(Player.loading && Player.id == id) onClicked: function() { if (Player.id != id) { Player.loadVideo(parent.parent.parent.id, parent.parent.parent.extension, parent.parent.parent.title, parent.parent.parent.position); } if (Player.playing) { Player.pause(); } else { Player.play(); } } } Label { heading: "h4" text: new Date(parent.parent.parent.position).toISOString().slice(14, 19) } Slider { Layout.fillWidth: true from: 0 to: parent.parent.parent.duration value: parent.parent.parent.position buffered: Player.id == id ? Player.buffered : 0 onMoved: parent.parent.parent.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.parent.fetchData() } } Timer { interval: 0 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; duration = data.metadata.duration * 1000; ratio = data.metadata.size[0] / data.metadata.size[1]; if (ratio == NaN) { ratio = 1.77777; } console.log(ratio); if (Player.id == id) { console.log("Already playing, this is not intended but possible in its current state so it's a feature, not a bug :3"); return; } Player.loadVideo(id, extension, title, position) } } xhr.ontimeout = function() { loading = false; failed = true; console.log("Request timed out"); } xhr.send(); } }