Rebrand to Offscale and rework the panel header
Forked from omarchy.tailscale at the packaged commit (omarchy-dev 4.0.0.r1744.gf002044). The `tailscale` branch holds the pristine upstream subtree history so upstream changes can still be merged in; `master` is this fork. - Rename the plugin to pastilhas.offscale: manifest id/name, moduleName and ipcTarget, and display strings. Deliberately NOT renamed: the lowercase "tailscale" CLI invocations, the TailscaleIPs/TailscaleIPv6 JSON fields from `tailscale status --json`, and authorizeTailscaleOperator. Renaming those loads fine but silently breaks peer parsing. - TailscaleIcon.qml -> OffscaleIcon.qml, now rendering offscale-logo.png instead of the 3x3 dot grid, keeping the crossed/warning states. - Add OffscaleHero.qml: a copy of qs.Ui.PanelHero with a titleComponent slot, so the wordmark (offscale-text.png) can replace the title text. Otherwise byte-identical to the original, so it stays diffable. - Drop the cycling hero phrases entirely - the array, the 2.8s timer and the metaOpacity fade. - Show the local machine as a PeerRow of its own, so it gets the same layout and copy menu as tailnet peers. Adds `navigable` to PeerRow so that row stays out of the peers keyboard cursor. - Enlarge the bar icon: BarIconButton pins its icon to opticalCanvas, so opticalSize/slotSize are overridden alongside iconSize. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Ui
|
||||
|
||||
// Local copy of qs.Ui.PanelHero with one addition: `titleComponent`.
|
||||
//
|
||||
// The stock hero renders `title` as a plain Text and offers no slot to put
|
||||
// anything else there, so showing the Offscale wordmark instead of a string
|
||||
// needed either editing a shared /usr/share component (never) or owning a
|
||||
// copy here. Everything else is unchanged from the original, so diffing
|
||||
// against /usr/share/omarchy/shell/Ui/PanelHero.qml shows exactly what we did.
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property Component iconComponent: null
|
||||
property string title: ""
|
||||
// When set, replaces the title Text. `title` is still used as the accessible
|
||||
// / fallback string, so callers should keep setting it.
|
||||
property Component titleComponent: null
|
||||
property string meta: ""
|
||||
property string detail: ""
|
||||
property color foreground: Color.foreground
|
||||
property string fontFamily: Style.font.family
|
||||
property real iconSize: Style.font.display
|
||||
property real iconOpacity: 1.0
|
||||
property alias metaOpacity: metaText.opacity
|
||||
|
||||
// Optional control pinned to the trailing edge of the hero — a ToggleSwitch,
|
||||
// a small button. The hero centers it against the labels and reserves the
|
||||
// space itself, so callers never do the geometry.
|
||||
property Component trailingControl: null
|
||||
|
||||
readonly property color dim: Qt.darker(foreground, 1.4)
|
||||
readonly property real trailingInset: trailingLoader.item && trailingLoader.item.visible ? trailingLoader.width + Style.space(12) : 0
|
||||
|
||||
width: parent ? parent.width : implicitWidth
|
||||
implicitHeight: Math.max(iconLoader.implicitHeight, heroLabels.implicitHeight, trailingLoader.implicitHeight)
|
||||
|
||||
Loader {
|
||||
id: iconLoader
|
||||
sourceComponent: root.iconComponent
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
opacity: root.iconOpacity
|
||||
}
|
||||
|
||||
Column {
|
||||
id: heroLabels
|
||||
anchors.left: iconLoader.right
|
||||
anchors.leftMargin: Style.space(14)
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: root.trailingInset
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
// Stock PanelHero uses space(2) = 3px, which is fine for two lines of text
|
||||
// but too tight under an image wordmark. space(5) = 8px gives the machine
|
||||
// name room to read as its own line.
|
||||
spacing: Style.space(5)
|
||||
|
||||
Row {
|
||||
id: titleRow
|
||||
visible: root.title !== "" || root.titleComponent !== null || detailPill.visible
|
||||
width: parent.width
|
||||
|
||||
// Either the custom title component or the stock Text — never both.
|
||||
Loader {
|
||||
id: titleSlot
|
||||
visible: root.titleComponent !== null
|
||||
active: root.titleComponent !== null
|
||||
sourceComponent: root.titleComponent
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
id: titleText
|
||||
visible: root.titleComponent === null && root.title !== ""
|
||||
text: root.title
|
||||
width: visible ? Math.min(implicitWidth, Math.max(0, parent.width - (detailPill.visible ? detailPill.implicitWidth + Style.space(8) : 0))) : 0
|
||||
color: root.foreground
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.title
|
||||
font.bold: true
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Item {
|
||||
width: Math.max(0, parent.width - titleSlot.width - titleText.width - detailPill.implicitWidth)
|
||||
height: 1
|
||||
}
|
||||
|
||||
BorderSurface {
|
||||
id: detailPill
|
||||
visible: root.detail !== ""
|
||||
implicitWidth: detailText.implicitWidth + Style.space(10)
|
||||
implicitHeight: detailText.implicitHeight + Style.space(4)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: "transparent"
|
||||
borderSpec: Border.controlSpec("normal", root.foreground, Color.accent)
|
||||
radius: Style.cornerRadius
|
||||
|
||||
Text {
|
||||
id: detailText
|
||||
anchors.centerIn: parent
|
||||
text: root.detail
|
||||
color: root.dim
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: metaText
|
||||
width: parent.width
|
||||
text: root.meta.toUpperCase()
|
||||
visible: text !== ""
|
||||
color: root.dim
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.caption
|
||||
font.bold: true
|
||||
font.letterSpacing: 1.2
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: trailingLoader
|
||||
sourceComponent: root.trailingControl
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user