Commit Graph
11 Commits
Author SHA1 Message Date
pastilhasandClaude Opus 5 22d94428f6 Scroll the machine list independently of the panel
With a dozen-plus peers the whole panel scrolled, pushing the header, THIS
MACHINE, CONNECTIONS and EXIT NODES off the top to reach the machines. The
list now has its own Flickable, capped at Style.space(260) — about five
rows — so those sections stay in view while the machines move under them.

The cap only applies once it is needed: implicitHeight is
min(content, max), so a tailnet with three machines still renders as a
short panel. The outer scroller stays for when the panel as a whole
outgrows the screen.

scrollItemIntoView() took a single hardcoded scroller, which would have
left j/k in the peers section scrolling the panel rather than the list, and
the highlighted row hidden inside a list that never moved. It now takes the
target scroller, defaulting to the panel; peer navigation scrolls the list
into view first, then the row within it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 17:14:57 +01:00
pastilhasandClaude Opus 5 92e284c11a Update the wordmark to the corrected artwork
Re-embeds OffScale_Text.png after the brand-colour correction upstream in
OfficerIcons — the gold in the asset is now #FECF03, matching root.accent
exactly rather than approximately.

The new source has a different aspect ratio (830x128 against 773x128), so
the divisor in the Image width binding moves with it; left alone the
wordmark would render squashed. Noted inline so a future asset swap
doesn't miss it.

Uses the plain variant rather than OffScale_Text_Light.png: the plain one
pairs the gold with near-white (#FEFEFE), the Light variant with dark
brown (#312D23) for light backgrounds. The panel is dark.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 02:57:32 +01:00
pastilhasandClaude Opus 5 54dec38b7e Clarify why the accent moved off the sampled value
The #FCC001 sample was accurate — the artwork was off-brand, and the icon
was recoloured to #FECF03 afterwards. The earlier note read as though
sampling had produced a wrong number, which is not what happened.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 02:34:43 +01:00
pastilhasandClaude Opus 5 954d4dbcf0 Use the canonical brand yellow #FECF03
Replaces #FCC001, which was measured off the hexagons in
OffScaleAppIcon.png. Sampling was the wrong approach: PNG antialiasing and
the icon's own shading make any eyedropper result an approximation of the
brand value rather than the value itself. #FECF03 (hue 48.8deg) is the
canonical one.

All three yellows resolve through root.accent — the bar's tailnet label,
the active connection name, and the IP/DNS subtitle — so this is a single
value. The wordmark asset is unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 02:30:47 +01:00
pastilhasandClaude Opus 5 04ac049a6f New app icon, brand yellow, and bar-icon size compensation
- Replace the mark with OffScaleAppIcon.png, run through the same pipeline
  as before: trim the transparent margin, pad to square, scale to 256x256
  (654 KB -> 62 KB). One asset, two render sites.

- Retune the accent to #FCC001, the modal hexagon fill of the new icon.
  Sampled from fully-opaque pixels only — the yellows cluster at
  252,192-196,1-2, so this is the flat colour and not an antialiased edge.
  (`magick -alpha off` flattens onto black and gives a wrong answer here.)
  Replaces #FAE204 from the previous logo, which was noticeably greener.
  All three yellows — the bar's tailnet label, the active connection name,
  and the IP/DNS subtitle — resolve through root.accent, so this is one
  value.

- Hold the bar mark at 32px now that shell base-size is 24 rather than 20.
  Every size in the shell is a multiple of fontScale, so raising base-size
  to enlarge the stock bar icons would have scaled this one identically and
  left the relative gap unchanged; the icon/canvas/slot values are scaled
  down to compensate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 01:47:41 +01:00
pastilhasandClaude Opus 5 bbdf6cfa61 Make the tailnet label open the panel
The label was a plain Text with its own MouseArea, which is not registered
in bar.clickTargets. While a panel is open, KeyboardPanel puts a
full-screen overlay above everything and forwards clicks landing in the
bar strip only to registered targets — so a left click opened the panel
and then had the same click treated as "outside", dismissing it. It
looked like nothing happened. Right click was unaffected because
toggleOffscale() never involves the panel.

Use a WidgetButton instead: it registers itself via syncClickRegistration()
and renders the label text natively, so both the Text and the MouseArea
go away. Left toggles the panel, right toggles Offscale, middle refreshes
— the same three buttons as the icon, so the widget reads as one target.

`dimmed` handles the inactive state rather than darkening the colour,
since Qt.darker on yellow shifts the hue to olive.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 22:43:41 +01:00
pastilhasandClaude Opus 5 91cf1130e0 Show the current tailnet next to the bar icon
Adds a label to the left of the mark naming the tailnet the selected
profile belongs to: the second-from-last label of the domain, so
offscale.pastilhas.dev reads "pastilhas" and headscale.pertento.ai reads
"pertento". Taking the second-level domain rather than a fixed index keeps
the distinctive part if a tailnet ever has four labels.

Read from the accounts list the service already polls, so no extra
process runs for it.

BarIconButton is icon-only by design (labelVisible: false, fixedWidth:
slotSize, and its `text` feeds a glyph rather than a label), so the label
could not live inside it — the bar widget is now a Row of label + button,
and its footprint comes from the row.

Coloured with the brand yellow, dimmed by opacity rather than by
darkening when Tailscale is off: Qt.darker on yellow shifts the hue to
olive instead of quietening it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 22:25:11 +01:00
pastilhasandClaude Opus 5 ca341c0e71 Rework the CONNECTIONS section
- Label each connection with its tailnet and account rather than the
  nickname alone. `tailscale switch --list --json` carries both, and on a
  multi-tailnet setup the nickname is the least useful field — "andre"
  says nothing about which tailnet you would be switching to. Renders as
  "headscale.pertento.ai (andre)", falling back through tailnet, then
  account, then profile id when a field is missing.

- Mark the active connection with colour instead of a filled background:
  brand yellow on its label, currentFill cleared. The theme sets
  selected-border-width to 0, so clearing the fill leaves nothing drawn.
  Hover still highlights through `fill`, so the row keeps its affordance.
  Exit-node and Mullvad-region rows are untouched and still fill.

- Sort the active connection to the top. Done in parseAccounts rather
  than at render time: the keyboard cursor indexes into
  tailscale.accounts, so sorting only in the view would leave j/k acting
  on a different row than the highlighted one. Array.sort is stable, so
  the remaining profiles keep the CLI's order.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 22:17:41 +01:00
pastilhasandClaude Opus 5 ad997bd6b1 Brand the panel: yellow IP/DNS line, white toggle
- Colour the IP / DNS subtitle under each machine with the logo yellow
  (#FAE204, sampled as the dominant opaque colour of offscale-logo.png).
  Stock draws that line through `dim` = Qt.darker(foreground, 1.55), which
  on yellow shifts the hue to olive (#A19203) rather than quietening it, so
  it takes the flat accent instead. Everything else keeps the themed
  foreground: section headers, machine names, account names and all the
  iconography.

- Add OffscaleToggle.qml so the switch reads white when on. The stock
  ToggleSwitch resolves its checked colours through
  Style.selectedStateColor / selectedFillFor, which read [controls]
  selected-color; Ethereal sets that to a literal "#ffcead" and
  Style.resolveStateColor returns literals verbatim, ignoring the
  foreground and accent properties entirely. No property on the stock
  switch can reach it, and overriding the token globally would recolour
  every selected state in the shell. The copy differs only in the checked
  state and needs an explicit `import qs.Ui`, which the original gets
  implicitly by living inside that module.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 17:31:30 +01:00
pastilhasandClaude Opus 5 b9bb75e8f5 Update the mark to OffscaleLogo3
Regenerated from OfficerIcons/NewBrief/OffscaleLogo3.png with the same
pipeline as before: trim the transparent margin, pad back to square so it
centres, scale to 256x256 (1.08 MB -> 78 KB).

One asset, two render sites — OffscaleIcon.qml loads it and is
instantiated both in the bar and in the panel hero, so this covers both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 17:13:01 +01:00
pastilhasandClaude Opus 5 0912b2b50d 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>
2026-08-15 17:04:41 +01:00