Files
magdev fcf7dc26cf
Some checks failed
CI / Quality (push) Successful in 5m3s
Release / Linux AppImage (push) Failing after 4m50s
qml: silence skeleton + todo Main.qml qmllint warnings
Two warnings, two distinct kinds of fix:

1. `Item { width: 12 }` (skeleton:77) — explicit width on a
   layout-managed Item is undefined behaviour per qmllint. Replaced
   with `Item { Layout.preferredWidth: 12 }`, matching the pattern
   already used at line 85 (`Item { Layout.fillWidth: true }`). Real
   fix, not a suppression.

2. `target: SingleInstance` (skeleton:48, todo/Main.qml:220) — false
   positive. SingleInstance is intentionally a context property set
   by main() before the QML engine boots (see SingleInstance.h
   doc comment), so qmllint can't see it via static analysis.
   Disabled the `unqualified` warning at the call site with an inline
   `// qmllint disable unqualified` directive plus a one-line
   explanation comment above. (Note: the disable directive parses
   every word after `disable` as a category name, so the prose has
   to live on the previous line — found the hard way after qmllint
   complained about the "unknown category" of every English word in
   the explanation.)

Verified `make quality` from framework/skeleton green (qmllint clean
across both targets — `php_qml_bridge_qmllint` and `skeleton_qmllint`
both build with zero warnings).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 11:05:17 +02:00

153 lines
4.8 KiB
QML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import PhpQml.Bridge
ApplicationWindow {
id: window
width: 760
height: 540
visible: true
title: "php-qml — skeleton"
RestClient {
id: rest
baseUrl: BackendConnection.url
token: BackendConnection.token
}
MercureClient {
id: mercure
hubUrl: BackendConnection.url + "/.well-known/mercure"
topic: "app://ping"
// No token in Phase 1 dev mode — Caddyfile enables `anonymous`
// for Mercure subscribers. Phase 4 swaps in a Mercure-issued JWT
// when the bundled mode tightens auth.
onUpdate: function(data, id) {
log.append("← mercure " + (id ? id.split(":").pop() : "") + " " + data)
}
onError: function(detail) {
log.append("× mercure error: " + detail)
}
}
Connections {
target: BackendConnection
function onConnectionStateChanged() {
if (BackendConnection.connectionState === BackendConnection.Online) {
if (!mercure.active) mercure.start()
} else {
if (mercure.active) mercure.stop()
}
}
}
Connections {
// SingleInstance is a context property set in main(); qmllint can't see it.
target: SingleInstance // qmllint disable unqualified
function onLaunchArgsReceived(args) {
window.requestActivate()
log.append("· launch args from peer: " + args.join(" "))
}
}
ColumnLayout {
anchors.fill: parent
anchors.margins: 16
spacing: 12
RowLayout {
spacing: 10
Layout.fillWidth: true
Rectangle {
Layout.preferredWidth: 12; Layout.preferredHeight: 12; radius: 6
color: {
switch (BackendConnection.connectionState) {
case BackendConnection.Online: return "#3ab36c"
case BackendConnection.Reconnecting: return "#d89614"
case BackendConnection.Offline: return "#d8503c"
default: return "#888"
}
}
}
Label { text: "Backend: " + window._stateName(BackendConnection.connectionState) }
Item { Layout.preferredWidth: 12 }
Rectangle {
Layout.preferredWidth: 12; Layout.preferredHeight: 12; radius: 6
color: mercure.active ? "#3ab36c" : "#666"
}
Label { text: "Mercure: " + (mercure.active ? "subscribed" : "off") }
Item { Layout.fillWidth: true }
Button {
text: "Ping"
enabled: BackendConnection.connectionState === BackendConnection.Online
onClicked: {
const t0 = Date.now()
rest.get("/api/ping").then(function(r) {
const dt = Date.now() - t0
log.append("→ ping " + dt + "ms " + JSON.stringify(r.body))
}).catch(function(e) {
log.append("× ping " + e.status + " " + JSON.stringify(e.problem || e.raw))
})
}
}
}
Label {
text: "URL: " + BackendConnection.url
+ (BackendConnection.error ? " error: " + BackendConnection.error : "")
color: BackendConnection.error ? "#d8503c" : "#888"
font.pixelSize: 12
elide: Text.ElideRight
Layout.fillWidth: true
}
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…"
}
}
}
DevConsole {
id: devConsole
visible: false
Layout.fillWidth: true
Layout.preferredHeight: 220
}
}
// Ctrl+` toggles the FrankenPHP child output console (Phase 5 §13).
Shortcut {
sequences: ["Ctrl+`", "Ctrl+~"]
onActivated: devConsole.visible = !devConsole.visible
}
function _stateName(s) {
switch (s) {
case BackendConnection.Connecting: return "connecting"
case BackendConnection.Online: return "online"
case BackendConnection.Reconnecting: return "reconnecting"
case BackendConnection.Offline: return "offline"
}
return "?"
}
}