Skip to content

Add Elsewhen, the world clock plugin for the Omarchy shell - #1

Merged
spencerbull merged 5 commits into
mainfrom
init-elsewhen
Sep 10, 2026
Merged

spencerbull merged 5 commits into
mainfrom
init-elsewhen

Conversation

@spencerbull

@spencerbull spencerbull commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

What this is

The initial import of Elsewhen, the world clock plugin for the Omarchy shell: a bar button that opens a panel of clocks, one row per city, with a spinnable orthographic globe behind it. The README carries the design notes; this PR body covers what changed for the import and what was checked.

Authorship

The plugin was written by Jason Fried (@jasonfried). The first commit on this branch is his code exactly as received, authored in his name; the commits after it are packaging by Spencer Bull.

Identity

The plugin arrived as jbf.worldclock. It is now omacom.elsewhen everywhere the id is load-bearing: the manifest, moduleName and ipcTarget in Panel.qml, the on-disk cache (~/.cache/omacom-elsewhen/), the user agent the data script sends, and the README's install and IPC examples. The manifest author and the LICENSE copyright name Jason Fried.

The manifest also gains smoothMotion, a boolean Panel.qml was already reading but the schema never declared.

Added for the repo

  • tests/run: runs every check under tests/ and exits non-zero if any fails. --offline skips the live Open-Meteo and FX cross-checks.
  • .github/workflows/ci.yml: two jobs. Manifest mirrors the checks in omarchy plugin validate (schema version, required fields, id shape and reserved namespace, entry points exist and are safe, a kind for every entry point, no symlinks), parses the data files, and compiles the python. Tests installs the Qt 6 test runner and iso-codes on ubuntu-latest and runs tests/run --offline.
  • LICENSE (MIT, Jason Fried) and .gitignore; the license text itself sits on main.
  • README: title, an Installing section with add/remove commands, the runtime dependencies and network sources, and a pointer to tests/run, which the marketplace listing requires.

Verified locally

  • tests/run passes: 13 node checks (4,984 assertions), the currency table against iso-codes and the live FX feed, and the QML pointer test under qmltestrunner (6 passed).
  • The runner fails when a test fails (checked by breaking an assertion).
  • omarchy plugin validate . passes on the current shell.
  • The host API the plugin uses exists on the installed shell (4.0.0.alpha): Panel.setting, KeyboardPanel, PanelKeyCatcher, BarIconButton, Style/Color tokens, and the scoped updateEntryInline a third-party widget gets for its own entry, which first-run seeding and city persistence depend on.
  • qmllint with the shell's import path reports no errors on any QML file.

Review

A read-only review pass over the branch turned up five findings. Three are fixed in the last commit, and the new tests fail on the old code:

  • IPC add could corrupt the zones setting. Model.addZone accepted any strings, so add Asia/Tokyo "Tokyo, Japan" came back from shell.json as two rows called Tokyo and Japan, and an id containing a delimiter turned into a different id. It now refuses an id parseZones would drop and replaces , and | in a label with spaces.
  • Row names rendered as auto-detected rich text. The row's label Text had no textFormat, so a label sent over IPC could carry markup. It is now Text.PlainText.
  • Model.hasZone was dead code. Removed.

Two are left for follow-up rather than folded into the import:

  • No wall-clock guard on the data script. refreshFacts waits on factsProc.running and nothing kills the process, so a hung network call (DNS that never answers, which python's socket timeout does not bound) would stop weather and currency refreshing for the rest of the session. The panel keeps working. A Quickshell-side timer that stops the process, plus incremental cache saves in the script so a killed run keeps its geocodes, is the fix.
  • IPC add returns the list after re-parsing, so a caller cannot tell an accepted add from a refused one. Cosmetic.

Not verified

  • Not loaded in a live shell on this machine. omarchy plugin add https://github.com/omacom/elsewhen.git --enable on a Quattro install is the remaining check.
  • No preview.png yet; the marketplace listing wants one.

Left as found

  • Panel.qml exposes a hereline IPC method marked TEMPORARY - remove with the header-arc trial; the three header styles it switches are still live UI, so it stays until that trial is settled.
  • The shelved features (Earth row, overlap band, sky tint) remain in the tree, off by default, as the README describes.

jasonfried and others added 5 commits September 9, 2026 21:49
A bar widget that opens a panel of clocks, one row per city, with a
spinnable orthographic globe behind it. Times come from a single date
probe per refresh because Qt's QML engine has no Intl; temperature and
currency come from a small python script with an on-disk cache. The
README carries the design notes.

Written by Jason Fried; committed as received, ahead of packaging.
The plugin id, IPC target, cache directory, user agent and the README's
install and IPC examples move from jbf.worldclock to omacom.elsewhen,
the repository this now lives in. The manifest declares smoothMotion,
which Panel.qml already read but the schema never listed, and the
README gains an Installing section with the add and remove commands,
the runtime dependencies and the network sources. Authorship stays
with Jason Fried in the manifest and the license.
tests/run runs every check under tests/ and exits non-zero if any of
them fails; CI calls it with --offline so a third-party feed hiccup
cannot fail a PR. A second job mirrors the checks in omarchy plugin
validate against manifest.json, parses the data files, and compiles
the python.
Model.addZone took any two strings, but the zones setting is a
"Label|Zone, Label|Zone" line: a label with a comma came back from
shell.json as two rows and an id with a delimiter became a different
id altogether. The picker never produced such input, but the IPC add
does, and it wrote the result straight into shell.json. addZone now
refuses an id parseZones would drop and replaces the two delimiters in
a label with spaces. The row's name is also drawn as plain text, so a
label can not be read as markup. hasZone had no callers and goes.
ubuntu-latest ships an iso-codes that predates ZWG, so CI flagged
Zimbabwe Gold as not a current ISO 4217 code. Allow that one by name,
the same way XK is allowed as a country, and say why.
@spencerbull
spencerbull merged commit 0da1736 into main Sep 10, 2026
2 checks passed
@spencerbull
spencerbull deleted the init-elsewhen branch September 10, 2026 02:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants