129 lines
3.8 KiB
QML
129 lines
3.8 KiB
QML
|
|
import QtQuick
|
|||
|
|
import QtQuick.Controls
|
|||
|
|
import QtQuick.Layouts
|
|||
|
|
import QtQuick.Window
|
|||
|
|
|
|||
|
|
ApplicationWindow {
|
|||
|
|
id: window
|
|||
|
|
width: 720
|
|||
|
|
height: 520
|
|||
|
|
visible: true
|
|||
|
|
title: "php-qml — Phase 0 spike"
|
|||
|
|
|
|||
|
|
readonly property string baseUrl: "http://127.0.0.1:8765"
|
|||
|
|
readonly property string topic: "app://ping"
|
|||
|
|
|
|||
|
|
property string status: "starting…"
|
|||
|
|
property string lastResponse: ""
|
|||
|
|
property string mercureState: "disconnected"
|
|||
|
|
|
|||
|
|
Mercure {
|
|||
|
|
id: mercure
|
|||
|
|
url: window.baseUrl + "/.well-known/mercure?topic=" + encodeURIComponent(window.topic)
|
|||
|
|
onEventReceived: function(data, id) {
|
|||
|
|
log.append("← event " + id.split(":").pop() + " " + data)
|
|||
|
|
}
|
|||
|
|
onStateChanged: function(s) {
|
|||
|
|
window.mercureState = s
|
|||
|
|
log.append("· mercure → " + s)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Timer {
|
|||
|
|
id: bootProbe
|
|||
|
|
interval: 250
|
|||
|
|
running: window.status !== "online"
|
|||
|
|
repeat: true
|
|||
|
|
onTriggered: {
|
|||
|
|
const xhr = new XMLHttpRequest()
|
|||
|
|
xhr.open("GET", window.baseUrl + "/api/ping")
|
|||
|
|
xhr.onreadystatechange = function() {
|
|||
|
|
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
|
|||
|
|
if (window.status !== "online") {
|
|||
|
|
window.status = "online"
|
|||
|
|
log.append("· backend ready")
|
|||
|
|
mercure.connect()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
xhr.send()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ColumnLayout {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
anchors.margins: 16
|
|||
|
|
spacing: 12
|
|||
|
|
|
|||
|
|
RowLayout {
|
|||
|
|
spacing: 10
|
|||
|
|
Layout.fillWidth: true
|
|||
|
|
|
|||
|
|
Rectangle {
|
|||
|
|
width: 12; height: 12; radius: 6
|
|||
|
|
color: window.status === "online" ? "#3ab36c" : "#d89614"
|
|||
|
|
}
|
|||
|
|
Label { text: "Backend: " + window.status }
|
|||
|
|
|
|||
|
|
Item { width: 12 }
|
|||
|
|
|
|||
|
|
Rectangle {
|
|||
|
|
width: 12; height: 12; radius: 6
|
|||
|
|
color: window.mercureState === "connected" ? "#3ab36c" : "#666"
|
|||
|
|
}
|
|||
|
|
Label { text: "Mercure: " + window.mercureState }
|
|||
|
|
|
|||
|
|
Item { Layout.fillWidth: true }
|
|||
|
|
|
|||
|
|
Button {
|
|||
|
|
text: "Ping"
|
|||
|
|
enabled: window.status === "online"
|
|||
|
|
onClicked: {
|
|||
|
|
const t0 = Date.now()
|
|||
|
|
const xhr = new XMLHttpRequest()
|
|||
|
|
xhr.open("GET", window.baseUrl + "/api/ping")
|
|||
|
|
xhr.onreadystatechange = function() {
|
|||
|
|
if (xhr.readyState === XMLHttpRequest.DONE) {
|
|||
|
|
const dt = Date.now() - t0
|
|||
|
|
if (xhr.status === 200) {
|
|||
|
|
window.lastResponse = xhr.responseText
|
|||
|
|
log.append("→ ping " + dt + "ms " + xhr.responseText)
|
|||
|
|
} else {
|
|||
|
|
log.append("× ping failed status=" + xhr.status)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
xhr.send()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Label {
|
|||
|
|
text: "Last response: " + (window.lastResponse || "—")
|
|||
|
|
color: "#888"
|
|||
|
|
font.pixelSize: 12
|
|||
|
|
Layout.fillWidth: true
|
|||
|
|
elide: Text.ElideRight
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Frame {
|
|||
|
|
Layout.fillWidth: true
|
|||
|
|
Layout.fillHeight: true
|
|||
|
|
padding: 0
|
|||
|
|
|
|||
|
|
ScrollView {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
|
|||
|
|
TextArea {
|
|||
|
|
id: log
|
|||
|
|
readOnly: true
|
|||
|
|
wrapMode: TextArea.Wrap
|
|||
|
|
font.family: "monospace"
|
|||
|
|
font.pixelSize: 12
|
|||
|
|
placeholderText: "events will appear here…"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|