Files
php-qml/spike/qt/Main.qml

129 lines
3.8 KiB
QML
Raw Normal View History

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…"
}
}
}
}
}