From a92cad45f3a15c61883656b9e6b5f30bf4b3b558 Mon Sep 17 00:00:00 2001 From: Leandro Felix Date: Mon, 9 Nov 2026 11:35:31 -0300 Subject: [PATCH 1/2] plugins: add ZimaOS 0.1.16 --- plugins/registry.json | 29 + plugins/zimaos/.gitignore | 5 + plugins/zimaos/AGENTS.md | 98 +++ plugins/zimaos/CLAUDE.md | 4 + plugins/zimaos/LICENSE | 21 + plugins/zimaos/README.md | 39 ++ plugins/zimaos/assets/preview-widget.png | Bin 0 -> 161842 bytes plugins/zimaos/bin/zima | 776 +++++++++++++++++++++++ plugins/zimaos/content/I18n.qml | 86 +++ plugins/zimaos/content/Panel.qml | 684 ++++++++++++++++++++ plugins/zimaos/content/Widget.qml | 83 +++ plugins/zimaos/content/zima-mark.png | Bin 0 -> 6014 bytes plugins/zimaos/manifest.json | 74 +++ plugins/zimaos/product-manifest.json | 113 ++++ plugins/zimaos/service/Main.qml | 509 +++++++++++++++ 15 files changed, 2521 insertions(+) create mode 100644 plugins/zimaos/.gitignore create mode 100644 plugins/zimaos/AGENTS.md create mode 100644 plugins/zimaos/CLAUDE.md create mode 100644 plugins/zimaos/LICENSE create mode 100644 plugins/zimaos/README.md create mode 100644 plugins/zimaos/assets/preview-widget.png create mode 100755 plugins/zimaos/bin/zima create mode 100644 plugins/zimaos/content/I18n.qml create mode 100644 plugins/zimaos/content/Panel.qml create mode 100644 plugins/zimaos/content/Widget.qml create mode 100644 plugins/zimaos/content/zima-mark.png create mode 100644 plugins/zimaos/manifest.json create mode 100644 plugins/zimaos/product-manifest.json create mode 100644 plugins/zimaos/service/Main.qml diff --git a/plugins/registry.json b/plugins/registry.json index ac9e1443..06d7277f 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -1381,6 +1381,35 @@ ], "lastUpdated": "2026-11-08", "upstream": "https://github.com/mysweetpea/prayer-times" + }, + { + "id": "zimaos", + "name": "ZimaOS", + "version": "0.1.16", + "path": "plugins/zimaos", + "author": "Felix ", + "summary": "QS Bar card for a ZimaOS server: device name, link rate, storage, and a shortcut to the dashboard.", + "description": "QS Bar card for a ZimaOS server: device name, link rate, storage, and a shortcut to the dashboard.", + "tags": [ + "zimaos", + "nas", + "bar-widget" + ], + "accent": "#8f8378", + "surface": "#101010", + "preview": "assets/preview-widget.png", + "screenshots": [ + "assets/preview-widget.png" + ], + "manifest": "product-manifest.json", + "manifestSha256": "60419e62d301345829f8579a2e3f2cb86c42be55252659cf00e0b0e298916fa8", + "official": false, + "tagline": "QS Bar card for a ZimaOS server: device name, link rate, storage, and a shortcut to the dashboard.", + "icon": "archive", + "hosts": [ + "topbarGlyph" + ], + "lastUpdated": "2026-11-09" } ] } diff --git a/plugins/zimaos/.gitignore b/plugins/zimaos/.gitignore new file mode 100644 index 00000000..e77ff271 --- /dev/null +++ b/plugins/zimaos/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +*.log +*.tmp +__pycache__/ +*.pyc diff --git a/plugins/zimaos/AGENTS.md b/plugins/zimaos/AGENTS.md new file mode 100644 index 00000000..2a23ee96 --- /dev/null +++ b/plugins/zimaos/AGENTS.md @@ -0,0 +1,98 @@ +# Agent guide for the zimaos plugin + +This folder is a Ryoku shell plugin. If you are an AI agent editing it, follow +every rule below. They are the same rules `ryoku plugin validate` enforces, so +work that breaks one will not install. This file is self-contained: you do not +need any other document to work here. + +## The rules + +R1 Place. A plugin is one folder named after its id. Author it under +`$(xdg-user-dir DOCUMENTS)/ryoku-plugins//` (fallback `~/ryoku-plugins//`); +`ryoku plugin new ` creates it there. Never write into +`~/.local/share/ryoku/plugins/` (the store's install root, receipt-owned) or +`~/.config/quickshell/` (the shipped shell). + +R2 Shape. `manifest.json` at the root; `service/Main.qml` (logic, no UI); +`content/Widget.qml` (the one view); optional `content/Panel.qml` (a bar panel); +`README.md`; `LICENSE`; `assets/preview-widget.png` (a real capture); scripts +only under `bin/` with a shebang and the exec bit. Every extra file listed in +manifest `files`. + +R3 Id. Lowercase `[a-z0-9][a-z0-9-]*`, unique, not a built-in widget id. + +R4 Imports. Only `QtQuick*`, `Quickshell*`, `Ryoku.PluginKit`, +`Ryoku.PluginKit.Singletons`, and files inside the plugin folder. Never +`shell.*`, `Ryoku.Ui*` internals, or a relative import that climbs out of the +folder. + +R5 Settings. Declared in `metadata.settings` (types the bar renders: toggle, +choice, multi, int, text); read through `pluginApi.pluginSettings` behind a +default; written only through `pluginApi.saveSetting(key, value)`. Never edit +`shell.json` or `plugins.json` directly. + +R6 Commands. Every external program the plugin runs is either in its own `bin/` +or listed in `dependencies.commands`. No `sudo`, `doas`, `su`. A privileged +action is allowed only through `pkexec`, only on an explicit click, only when +listed in manifest `capabilities.privileged` (exact command strings) and +explained in README. + +R7 Network. Every host the plugin talks to is listed in +`capabilities.network`. No `curl … | sh`, no downloading and running code. + +R8 Files. Write only under `pluginApi.stateDir` +(`$XDG_STATE_HOME/ryoku/plugins/`), `$XDG_CACHE_HOME/ryoku/plugins/`, or +a temp dir. Never touch `~/.ssh`, `/etc`, shell rc files, or another plugin's +folder. + +R9 Shell. No `sh -c` with a string built from settings or program output +(injection). Pass argv arrays. + +R10 Secrets and binaries. No tokens, keys or credentials in the tree; no +compiled binaries (ELF/Mach-O/.so); scripts only. + +R11 Honesty. `official` is never true for a community plugin. `author` is +`Name `. README says what runs, what it reads, what it writes, and every +privileged/network capability. + +## The workflow + +1. `ryoku plugin new [--bar|--desktop|--popout|--sidebar]` scaffolds this + folder (already done). This scaffold selected `topbarGlyph`. +2. Edit `service/Main.qml` for logic and `content/Widget.qml` for the view. + Edit `content/Panel.qml` only for a bar plugin. Capture + `assets/preview-widget.png`. +3. `ryoku plugin validate ` and fix every blocking finding (warnings are + advisory but read them). +4. `ryoku plugin add --yes`, then enable and place it under + **Ryoku Settings > Add-ons**. For a bar plugin, `--bar` enables it on the + current bar immediately. +5. `ryoku plugin share ` ONLY when the user asks to publish. Never share a + plugin unless asked. + +## What the host sets + +Ryoku ships four hosts: `topbarGlyph`, `desktopWidget`, `framePopout`, and +`sidebarCard`. They all mount `content/Widget.qml`; only a bar plugin may add +`content/Panel.qml`. + +The bar, desktop, and popout hosts set `pluginApi`, `s`, `active`, `density`, and +`widthBudget`. Read them; never assign them. + +For `sidebarCard`, the widget root is an `Item` with +`pragma ComponentBehavior: Bound`. The host sets `s`, `open`, `reveal`, +`tabActive`, `width`, and `pluginApi`; the card reports `implicitHeight` and +declares `signal requestClose()`. Read host-set values and never assign them. +There is no `content/Sidebar.qml`. Ryoku draws the card plate and owns its +position, size, motion, and chrome. + +`pluginApi` exposes: + +- `mainInstance`: the live `service/Main.qml` instance every view shares. +- `pluginSettings`: the resolved settings object; read behind a default. +- `pluginDir`: this plugin's folder. +- `stateDir`: `$XDG_STATE_HOME/ryoku/plugins/`; the only place to write. +- `saveSetting(key, value)`: persist one setting. +- `panelOpen` (bool), `openPanel()`, `closePanel()`, `togglePanel()`: the bar + panel controls (present but inert off the bar). The sanctioned bar-widget + click is `onClicked: pluginApi.togglePanel()`. diff --git a/plugins/zimaos/CLAUDE.md b/plugins/zimaos/CLAUDE.md new file mode 100644 index 00000000..3c35c327 --- /dev/null +++ b/plugins/zimaos/CLAUDE.md @@ -0,0 +1,4 @@ +# CLAUDE.md + +Read `AGENTS.md` in this folder before editing anything here. +It holds every rule this plugin must follow and the full authoring workflow. diff --git a/plugins/zimaos/LICENSE b/plugins/zimaos/LICENSE new file mode 100644 index 00000000..de70bacb --- /dev/null +++ b/plugins/zimaos/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Felix + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/zimaos/README.md b/plugins/zimaos/README.md new file mode 100644 index 00000000..018f3c9d --- /dev/null +++ b/plugins/zimaos/README.md @@ -0,0 +1,39 @@ +# ZimaOS + +Plugin da QS Bar para um servidor ZimaOS. O ícone na barra é o nome ZIMA, num tom só, igual aos outros glifos, e abre o painel. Antes de entrar, o painel pede o endereço, o usuário e a senha. Depois de entrar, mostra o cartão do aparelho. + +## O que aparece + +Antes do login: **IP**, **Usuário** e **Senha**, e o botão **Entrar**. O IP fica preenchido quando já existe um endereço salvo. O exemplo do campo é só um placeholder. + +Depois do login, no ZimaOS 1.8: + +- Nome do aparelho, versão e modelo, lidos de `GET /v2/zimaos/device/info`. A foto do aparelho vem de `device_image` nesse mesmo JSON e é baixada de `/v2/zimaos/device/image?model=…&type=client`. O PNG fica em `$XDG_STATE_HOME/ryoku/plugins/zimaos/device.png` e só é baixado de novo quando o modelo muda. +- Interface e endereço IPv4 do caminho em uso (`GET /v2/zimaos/network/connection-status`). Os quatro ícones ao lado de LAN são remoto, Wi-Fi, Ethernet e Thunderbolt: o acento marca o caminho em uso, o tom claro marca um caminho disponível, e o tom apagado marca o que está desligado. +- Atalho **Ir ao painel** para a página inicial do servidor. +- Atalho **Abrir** o armazenamento (`/modules/icewhale_files/`), com o espaço livre do maior volume. O nome do volume só aparece depois do login. +- **Backup**, quando o app grid devolve um link; senão abre o painel. +- **PeerDrop** abre o módulo do servidor em `/modules/icewhale_peerdrop/`. +- **Sair** volta à mesma tela de entrar, com o IP salvo preenchido e a senha vazia. +- O cartão usa a superfície da própria barra: a mesma borda e o mesmo vidro do painel de música. Os blocos de dentro são um escurecimento leve, não uma placa opaca. + +## O que corre, lê e escreve + +- `bin/zima` (Python 3, biblioteca padrão). Um IP ou nome da rede local, sem esquema, continua em HTTP (por exemplo `192.168.0.180`). `http://` é o mesmo. `https://` usa HTTPS e verifica o certificado; a verificação não é desligada. Recusa caminho, `@` e qualquer outro esquema. Não segue redirecionamentos, para o token não ir para outro host. +- Caminhos: `POST /v1/users/login`, `POST /v1/users/refresh`, `GET /v1/sys/utilization`, `GET /v2/zimaos/network/interfaces`, `GET /v2/zimaos/network/connection-status`, `GET /v2/local_storage/storages`, `GET /v2/app_management/web/appgrid` e o device info acima. +- `xdg-open`, só quando você clica num atalho. +- O endereço é gravado com `pluginApi.saveSetting` na chave `host`. A senha não é gravada nem registrada. +- A sessão (usuário e tokens) fica em `$XDG_STATE_HOME/ryoku/plugins/zimaos/session.json`, modo `0600`. A foto do aparelho fica ao lado, em `device.png`. + +Não há comando privilegiado. Não há host fixo em `capabilities.network`: o validador do Ryoku só exige essa lista para endereços `http://` ou `https://` escritos no código, e este plugin não tem nenhum. O servidor é o que a pessoa digita. + +## Instalar + +Outra pessoa com Ryoku copia esta pasta e roda, dentro dela: + +``` +ryoku plugin validate . +ryoku plugin add . --bar --yes +``` + +O glifo entra na barra. Abra o painel, informe o IP do ZimaOS, o usuário e a senha, e toque em **Entrar**. O mesmo plugin fica em **QS Bar Settings → Community**. diff --git a/plugins/zimaos/assets/preview-widget.png b/plugins/zimaos/assets/preview-widget.png new file mode 100644 index 0000000000000000000000000000000000000000..24689bff5863631c14275f0817ec7848bf2e503d GIT binary patch literal 161842 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

$%`&Qsz3#R_+VvWVFAqSp-;kbBMs}{ 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 ECawn~jt9mwM!ZiNIQO6gDNA$V&3XlW>X~h1 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 D#PYRC literal 0 HcmV?d00001 diff --git a/plugins/zimaos/bin/zima b/plugins/zimaos/bin/zima new file mode 100755 index 00000000..3082faf5 --- /dev/null +++ b/plugins/zimaos/bin/zima @@ -0,0 +1,776 @@ +#!/usr/bin/env python3 +"""Talk to one ZimaOS box the way its own web UI does. + +Paths were taken from the UI shipped on the Zotac (ZimaOS v1.8): + GET /v2/zimaos/device/info public device card + GET /v2/zimaos/device/image product render (type=client) + POST /v1/users/login username + password -> session + POST /v1/users/refresh {"refresh_token"} + GET /v1/sys/utilization cpu, memory, interface counters + GET /v2/zimaos/network/interfaces interface name and IPv4 + GET /v2/zimaos/network/connection-status path in use: LAN, Remote, Thunderbolt + GET /v2/local_storage/storages pools such as ZimaOS-HD + GET /v2/app_management/web/appgrid installed apps, for a Backup link + GET /modules/icewhale_peerdrop/ PeerDrop page opened from the card + +Authorization is the raw access token, the same header the dashboard sends. +The session file is only written when its path is the plugin state file. +""" + +import json +import os +import re +import ssl +import sys +import urllib.error +import urllib.parse +import urllib.request + +TIMEOUT = 4 +STORAGE_TIMEOUT = 6 + + +def die(message, code=1): + sys.stdout.write(json.dumps({"ok": False, "error": message}, ensure_ascii=False)) + sys.stdout.write("\n") + raise SystemExit(code) + + +def normalize_host(raw): + text = (raw or "").strip() + # A typed LAN host has no scheme and stays http. https:// is opt-in and + # keeps certificate verification. Anything else is rejected. + scheme = "" + lowered = text.lower() + if lowered.startswith("https://"): + scheme = "https" + text = text[8:] + elif lowered.startswith("http://"): + scheme = "http" + text = text[7:] + if text == "" or "@" in text or "://" in text or "/" in text or "\\" in text or " " in text: + die("invalid address") + host, port = text, None + if host.startswith("["): + end = host.find("]") + if end < 0: + die("invalid address") + port = host[end + 1 :] + host = host[: end + 1] + if port.startswith(":"): + port = port[1:] + elif port != "": + die("invalid address") + elif host.count(":") == 1: + host, port = host.split(":", 1) + elif host.count(":") > 1: + die("invalid address") + ipv4 = re.fullmatch(r"(?:\d{1,3}\.){3}\d{1,3}", host or "") + name = re.fullmatch( + r"[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*", + host or "", + ) + if ipv4: + parts = [int(p) for p in host.split(".")] + if any(p > 255 for p in parts): + die("invalid address") + elif not name: + die("invalid address") + if port is not None and port != "": + if not re.fullmatch(r"\d{1,5}", port) or not (1 <= int(port) <= 65535): + die("invalid address") + location = host + ":" + str(int(port)) + else: + location = host + if scheme == "https": + return "https://" + location + return location + + +def request_origin(host): + """Return (scheme, location) for a host from normalize_host. + + A bare address is http, so a LAN host such as 192.168.0.180 is not upgraded. + An explicit http:// prefix is the same. https:// keeps the scheme so the + default TLS context can verify the server. + """ + if host.startswith("https://"): + return "https", host[len("https://") :] + if host.startswith("http://"): + return "http", host[len("http://") :] + return "http", host + + +def origin_base(host): + scheme, location = request_origin(host) + return scheme + "://" + location + + +def state_path(raw): + path = os.path.realpath(raw or "") + marker = "/ryoku/plugins/zimaos/" + if marker not in path or not path.endswith("/session.json"): + die("refusing to touch a file outside the plugin state directory") + parent = os.path.dirname(path) + if not os.path.isdir(parent): + os.makedirs(parent, mode=0o700, exist_ok=True) + return path + + +class _NoRedirect(urllib.request.HTTPRedirectHandler): + """Do not follow redirects. urllib would resend Authorization to the new host.""" + + def redirect_request(self, req, fp, code, msg, headers, newurl): + return None + + def http_error_302(self, req, fp, code, msg, headers): + return fp + + http_error_301 = http_error_303 = http_error_307 = http_error_308 = http_error_302 + + +# Default context verifies certificates. It is only used when a URL is https. +# LAN hosts stay http:// — ZimaOS on the local network does not speak TLS. +_HTTPS = ssl.create_default_context() + + +def _opener(): + return urllib.request.build_opener( + _NoRedirect(), + urllib.request.HTTPSHandler(context=_HTTPS), + ) + + +def request_bytes(host, method, path, token=None, body=None, timeout=TIMEOUT): + # Same opener for both schemes: redirects stay off, so Authorization is not + # forwarded, and HTTPS uses the default context (verify the certificate). + if not path.startswith("/"): + path = "/" + path + url = origin_base(host) + path + data = None + headers = {"Accept": "*/*"} + if body is not None: + data = json.dumps(body).encode("utf-8") + headers["Content-Type"] = "application/json" + if token: + headers["Authorization"] = token + req = urllib.request.Request(url, data=data, headers=headers, method=method) + try: + with _opener().open(req, timeout=timeout) as res: + return res.status, res.read() + except urllib.error.HTTPError as exc: + return exc.code, exc.read() + except Exception: + return 0, b"" + + +def request(host, method, path, token=None, body=None, timeout=TIMEOUT): + status, raw = request_bytes(host, method, path, token=token, body=body, timeout=timeout) + if status == 0: + return 0, {"_error": "no route to ZimaOS"} + if not raw: + return status, None + try: + return status, json.loads(raw.decode("utf-8", "replace")) + except json.JSONDecodeError: + return status, {"_error": "not json", "_body": raw[:180].decode("utf-8", "replace")} + + +def unwrap(payload): + if isinstance(payload, dict) and "data" in payload and ( + "success" in payload or "Success" in payload or "message" in payload + ): + return payload.get("data") + return payload + + +def as_number(value): + if isinstance(value, bool) or value is None: + return None + if isinstance(value, (int, float)): + return float(value) + if isinstance(value, str): + try: + return float(value) + except ValueError: + return None + return None + + +def first(obj, keys): + if not isinstance(obj, dict): + return None + for key in keys: + if key in obj and obj[key] not in (None, ""): + return obj[key] + return None + + +def load_session(path): + try: + with open(path, "r", encoding="utf-8") as handle: + data = json.load(handle) + except (OSError, json.JSONDecodeError): + return {} + return data if isinstance(data, dict) else {} + + +def save_session(path, data): + stored = {key: value for key, value in data.items() if key != "password"} + tmp = path + ".tmp" + fd = os.open(tmp, os.O_CREAT | os.O_WRONLY | os.O_TRUNC, 0o600) + owned = True + try: + os.fchmod(fd, 0o600) + with os.fdopen(fd, "w", encoding="utf-8") as handle: + owned = False + json.dump(stored, handle, ensure_ascii=False) + handle.write("\n") + except Exception: + if owned: + try: + os.close(fd) + except OSError: + pass + try: + os.unlink(tmp) + except OSError: + pass + raise + os.replace(tmp, path) + os.chmod(path, 0o600) + + +def session_for_host(path, host): + """Return the session only when it was issued for this host. + + A token saved for another server is discarded and never sent. The password + is never kept in the file. + """ + session = load_session(path) + if not session: + return {} + had_password = "password" in session + session.pop("password", None) + if session.get("host") != host: + try: + os.remove(path) + except OSError: + pass + return {} + if had_password: + save_session(path, session) + return session + + +def dig_token(payload): + if not isinstance(payload, dict): + return None + if "access_token" in payload and payload.get("access_token"): + return payload + nested = payload.get("token") + if isinstance(nested, dict) and nested.get("access_token"): + return nested + data = payload.get("data") + if isinstance(data, dict): + return dig_token(data) + return None + + +def message_of(payload): + if isinstance(payload, dict): + for key in ("message", "Message", "_error"): + if payload.get(key): + return str(payload[key]) + data = payload.get("data") + if isinstance(data, dict): + return message_of(data) + return "request failed" + + +def login(host, path): + try: + incoming = json.loads(sys.stdin.read() or "{}") + except json.JSONDecodeError: + die("invalid login payload") + username = str(incoming.get("username") or "").strip() + password = str(incoming.get("password") or "") + if username == "" or password == "": + die("username and password are required") + status, payload = request( + host, + "POST", + "/v1/users/login", + body={"username": username, "password": password}, + ) + token = dig_token(payload) + if status != 200 or not token: + die(message_of(payload) or "login failed") + save_session( + path, + { + "host": host, + "username": username, + "access_token": token.get("access_token") or "", + "refresh_token": token.get("refresh_token") or "", + }, + ) + sys.stdout.write(json.dumps({"ok": True, "username": username}, ensure_ascii=False)) + sys.stdout.write("\n") + + +def logout(path): + try: + os.remove(path) + except FileNotFoundError: + pass + sys.stdout.write(json.dumps({"ok": True}) + "\n") + + +def refresh(host, session): + refresh_token = session.get("refresh_token") or "" + if not refresh_token: + return False + status, payload = request( + host, "POST", "/v1/users/refresh", body={"refresh_token": refresh_token} + ) + token = dig_token(payload) + if status != 200 or not token or not token.get("access_token"): + return False + session["access_token"] = token.get("access_token") or "" + if token.get("refresh_token"): + session["refresh_token"] = token.get("refresh_token") + return True + + +def authed_get(host, path, session, timeout=TIMEOUT): + token = session.get("access_token") or "" + if not token: + return 401, None + status, payload = request(host, "GET", path, token=token, timeout=timeout) + if status != 401: + return status, payload + if not refresh(host, session): + session["access_token"] = "" + session["refresh_token"] = "" + return 401, payload + status, payload = request( + host, "GET", path, token=session.get("access_token") or "", timeout=timeout + ) + return status, payload + + +def device_view(payload): + data = unwrap(payload) + if not isinstance(data, dict): + return None + name = first(data, ("device_name", "name", "hostname")) + if not name: + return None + memory = data.get("memory") if isinstance(data.get("memory"), dict) else {} + cpu = data.get("cpu") if isinstance(data.get("cpu"), dict) else {} + model = str(data.get("device_model") or "") + if model.strip("X") == "" or model.lower() in ("unknown", "generic"): + model = "" + return { + "deviceName": str(name), + "osVersion": str(data.get("os_version") or ""), + "deviceModel": model, + "cpuModel": str(cpu.get("model") or ""), + "memoryBytes": as_number(memory.get("total_byte")), + } + + +def pick_ipv4(value): + if isinstance(value, str) and re.fullmatch(r"(?:\d{1,3}\.){3}\d{1,3}", value): + return value + if isinstance(value, list): + for item in value: + found = pick_ipv4(item if not isinstance(item, dict) else first(item, ("address", "ip", "ipv4"))) + if found: + return found + if isinstance(value, dict): + return pick_ipv4(first(value, ("address", "ip", "ipv4", "ipv4_address"))) + return "" + + +def iface_label(item): + text = str(first(item, ("connection", "connection_name", "label", "type", "name")) or "") + lowered = text.lower() + if lowered in ("ethernet", "lan", "wired"): + return "Ethernet" + if "wi" in lowered or "wlan" in lowered: + return "Wi-Fi" + return text or "LAN" + + +def iface_address(item): + return pick_ipv4(first(item, ("ipv4", "ip", "address", "addresses", "ipv4_address", "addr"))) or "" + + +def connect_kind(item): + text = str(item.get("connect_type") or "").lower() + name = str(item.get("name") or "").lower() + if "thunder" in text or "thunder" in name: + return "thunderbolt" + if "remote" in text or name.startswith("zt"): + return "remote" + if "wi" in text or "wlan" in name or name.startswith("wl"): + return "wifi" + if "ethernet" in text or name.startswith("eth") or name.startswith("en"): + return "ethernet" + return "" + + +def counter_kind(name): + low = str(name or "").lower() + if low.startswith("wlan") or low.startswith("wl") or "wifi" in low: + return "wifi" + if "thunder" in low: + return "thunderbolt" + if low.startswith("eth") or low.startswith("en"): + return "ethernet" + return "" + + +def link_up(item, states): + name = str(item.get("name") or "") + state = states.get(name, "") + if state == "down": + return False + if state == "up": + return True + if iface_address(item): + return True + speed = as_number(item.get("negotiated_speed")) + return speed is not None and speed > 0 + + +def network_view(payload, counters, connection): + data = unwrap(payload) + items = data if isinstance(data, list) else [] + if isinstance(data, dict): + for key in ("interfaces", "list", "nets"): + if isinstance(data.get(key), list): + items = data[key] + break + nets = [net for net in (counters or []) if isinstance(net, dict)] + states = {} + for net in nets: + name = str(net.get("name") or "") + if name: + states[name] = str(net.get("state") or "").lower() + remote = wifi = ethernet = thunderbolt = False + for item in items: + if not isinstance(item, dict): + continue + kind = connect_kind(item) + if kind and link_up(item, states): + if kind == "remote": + remote = True + elif kind == "wifi": + wifi = True + elif kind == "ethernet": + ethernet = True + elif kind == "thunderbolt": + thunderbolt = True + for name, state in states.items(): + if state != "up": + continue + kind = counter_kind(name) + if kind == "wifi": + wifi = True + elif kind == "ethernet": + ethernet = True + elif kind == "thunderbolt": + thunderbolt = True + conn = unwrap(connection) + if not isinstance(conn, dict): + conn = {} + status = str(conn.get("status") or "") + active = "" + if status == "Remote": + active = "remote" + remote = True + elif status == "Thunderbolt": + active = "thunderbolt" + thunderbolt = True + elif status == "LAN": + if ethernet and not wifi: + active = "ethernet" + elif ethernet and wifi: + active = "lan" + else: + active = "wifi" + wifi = True + chosen = None + for item in items: + if not isinstance(item, dict): + continue + if iface_address(item): + chosen = item + break + if chosen is None and items and isinstance(items[0], dict): + chosen = items[0] + label = status if status in ("LAN", "Remote", "Thunderbolt") else (iface_label(chosen) if chosen else "LAN") + ip = pick_ipv4(conn.get("ip")) or (iface_address(chosen) if chosen else "") + wanted = active if active in ("wifi", "ethernet", "thunderbolt") else "" + preferred = None + for net in nets: + name = str(net.get("name") or "") + if name in ("lo", "docker0"): + continue + if wanted and counter_kind(name) == wanted and states.get(name) == "up": + preferred = net + break + if preferred is None: + preferred = net + sent = recv = stamp = None + if preferred: + sent = as_number(first(preferred, ("bytesSent", "bytes_sent", "tx", "transmit"))) + recv = as_number(first(preferred, ("bytesRecv", "bytes_recv", "rx", "receive"))) + stamp = as_number(first(preferred, ("time", "timestamp"))) + return { + "label": label, + "ip": ip, + "bytesSent": sent, + "bytesRecv": recv, + "time": stamp, + "remote": remote, + "wifi": wifi, + "ethernet": ethernet, + "thunderbolt": thunderbolt, + "active": active, + } + + +def storage_bytes(item): + total = as_number(first(item, ("size", "total", "total_size", "bytes", "capacity"))) + avail = as_number(first(item, ("avail", "available", "free", "free_size"))) + used = as_number(first(item, ("used", "used_size", "usage"))) + if total is None and used is not None and avail is not None: + total = used + avail + if used is None and total is not None and avail is not None: + used = max(0, total - avail) + return total, used, avail + + +def storage_view(payload): + data = unwrap(payload) + items = [] + if isinstance(data, list): + items = data + elif isinstance(data, dict): + for key in ("storages", "disks", "list", "children"): + if isinstance(data.get(key), list): + items = data[key] + break + if not items and first(data, ("name", "label", "mount_point")): + items = [data] + best = None + best_size = -1 + for item in items: + if not isinstance(item, dict): + continue + name = str(first(item, ("name", "label", "mount_point")) or "") + if name in ("", "/", "loop"): + continue + total, used, avail = storage_bytes(item) + size = total if total is not None else -1 + if size >= best_size: + best = {"name": name, "total": total, "used": used, "avail": avail} + best_size = size + return best + + +def find_backup(payload, host): + found = [] + scheme, location = request_origin(host) + + def walk(node): + if isinstance(node, dict): + bits = [] + for key in ("name", "id", "app", "scheme", "hostname", "title", "en_us", "en_US"): + value = node.get(key) + if isinstance(value, str): + bits.append(value) + title = node.get("title") + if isinstance(title, dict): + bits.extend(str(v) for v in title.values() if isinstance(v, str)) + blob = " ".join(bits).lower() + url = node.get("url") if isinstance(node.get("url"), str) else "" + if not url.startswith("http"): + index = node.get("index") if isinstance(node.get("index"), str) else "" + port = node.get("port") or node.get("port_map") + raw_host = node.get("hostname") if isinstance(node.get("hostname"), str) else location + if "://" not in raw_host and "/" not in raw_host and "\\" not in raw_host: + if raw_host.startswith("[") and "]" in raw_host: + bare = raw_host[: raw_host.find("]") + 1] + else: + bare = raw_host.split(":")[0] + if bare and isinstance(port, str) and port.isdigit() and index.startswith("/"): + url = scheme + "://" + bare + ":" + port + index + elif bare and isinstance(port, int) and index.startswith("/"): + url = scheme + "://" + bare + ":" + str(port) + index + if "backup" in blob and url.startswith("http"): + found.append(url) + for value in node.values(): + walk(value) + elif isinstance(node, list): + for value in node: + walk(value) + + walk(payload) + return found[0] if found else "" + + +def utilization_view(payload): + data = unwrap(payload) + if not isinstance(data, dict): + return {} + cpu = data.get("cpu") if isinstance(data.get("cpu"), dict) else {} + mem = data.get("mem") if isinstance(data.get("mem"), dict) else {} + return { + "cpuPercent": as_number(first(cpu, ("percent", "usage", "usedPercent"))), + "memPercent": as_number(first(mem, ("usedPercent", "percent", "usage"))), + "memUsed": as_number(first(mem, ("used", "used_bytes"))), + "memTotal": as_number(first(mem, ("total", "total_bytes"))), + "net": data.get("net") if isinstance(data.get("net"), list) else [], + } + + +def client_image_path(payload): + data = unwrap(payload) + if not isinstance(data, dict): + return "" + raw = data.get("device_image") or data.get("device_image_path") or "" + if not isinstance(raw, str): + return "" + parsed = urllib.parse.urlparse(raw) + if parsed.scheme or parsed.netloc or parsed.path != "/v2/zimaos/device/image": + return "" + query = urllib.parse.parse_qs(parsed.query, keep_blank_values=False) + model = (query.get("model") or [""])[0] + if not re.fullmatch(r"[A-Za-z0-9_-]{1,64}", model): + return "" + return "/v2/zimaos/device/image?model=" + model + "&type=client" + + +def ensure_device_image(host, info_payload, session_file): + rel = client_image_path(info_payload) + parent = os.path.dirname(session_file) + dest = os.path.join(parent, "device.png") + stamp = os.path.join(parent, "device-image.txt") + if not rel: + return dest if os.path.isfile(dest) else "" + try: + if os.path.isfile(dest) and os.path.getsize(dest) > 32: + with open(stamp, "r", encoding="utf-8") as handle: + if handle.read().strip() == rel: + return dest + except OSError: + pass + status, raw = request_bytes(host, "GET", rel, timeout=8) + if status != 200 or not raw.startswith(b"\x89PNG\r\n\x1a\n"): + return dest if os.path.isfile(dest) else "" + tmp = dest + ".tmp" + with open(tmp, "wb") as handle: + handle.write(raw) + os.chmod(tmp, 0o644) + os.replace(tmp, dest) + with open(stamp, "w", encoding="utf-8") as handle: + handle.write(rel + "\n") + return dest + + +def status(host, path): + code, payload = request(host, "GET", "/v2/zimaos/device/info") + device = device_view(payload) if code == 200 else None + if not device: + detail = message_of(payload) if isinstance(payload, dict) else "no route to ZimaOS" + die(detail or "ZimaOS did not answer") + session = session_for_host(path, host) + result = { + "ok": True, + "authed": False, + "authError": "", + "username": session.get("username") or "", + "dashboardUrl": origin_base(host) + "/", + "filesUrl": origin_base(host) + "/modules/icewhale_files/", + "peerDropUrl": origin_base(host) + "/modules/icewhale_peerdrop/", + "backupUrl": "", + } + result.update(device) + result["deviceImage"] = ensure_device_image(host, payload, path) + if not session.get("access_token") and not session.get("refresh_token"): + sys.stdout.write(json.dumps(result, ensure_ascii=False) + "\n") + return + u_code, u_payload = authed_get(host, "/v1/sys/utilization", session) + n_code, n_payload = authed_get(host, "/v2/zimaos/network/interfaces", session) + c_code, c_payload = authed_get(host, "/v2/zimaos/network/connection-status", session) + s_code, s_payload = authed_get( + host, "/v2/local_storage/storages", session, timeout=STORAGE_TIMEOUT + ) + if u_code == 401 or n_code == 401 or c_code == 401: + result["authError"] = "session expired" + if session.get("access_token"): + save_session(path, session) + sys.stdout.write(json.dumps(result, ensure_ascii=False) + "\n") + return + result["authed"] = True + usage = utilization_view(u_payload if u_code == 200 else {}) + net = network_view( + n_payload if n_code == 200 else {}, + usage.pop("net", []), + c_payload if c_code == 200 else {}, + ) + result.update(usage) + result["network"] = net + storage = storage_view(s_payload) if s_code == 200 else None + if storage: + result["storage"] = storage + g_code, g_payload = authed_get(host, "/v2/app_management/web/appgrid", session) + if g_code == 200: + result["backupUrl"] = find_backup(g_payload, host) + # App grid is the last authenticated call and can rotate the refresh token. + # Persist after it, or the next poll keeps the tokens from before that call. + if session.get("access_token"): + save_session(path, session) + sys.stdout.write(json.dumps(result, ensure_ascii=False) + "\n") + + +def main(argv): + if len(argv) < 2: + die("usage: zima device|login|logout|status") + cmd = argv[1] + if cmd == "device": + if len(argv) != 3: + die("usage: zima device ") + host = normalize_host(argv[2]) + code, payload = request(host, "GET", "/v2/zimaos/device/info") + device = device_view(payload) if code == 200 else None + if not device: + die(message_of(payload) if isinstance(payload, dict) else "ZimaOS did not answer") + device["ok"] = True + sys.stdout.write(json.dumps(device, ensure_ascii=False) + "\n") + return + if cmd == "login": + if len(argv) != 4: + die("usage: zima login ") + login(normalize_host(argv[2]), state_path(argv[3])) + return + if cmd == "logout": + if len(argv) != 3: + die("usage: zima logout ") + logout(state_path(argv[2])) + return + if cmd == "status": + if len(argv) != 4: + die("usage: zima status ") + status(normalize_host(argv[2]), state_path(argv[3])) + return + die("unknown command") + + +if __name__ == "__main__": + main(sys.argv) diff --git a/plugins/zimaos/content/I18n.qml b/plugins/zimaos/content/I18n.qml new file mode 100644 index 00000000..368d0f72 --- /dev/null +++ b/plugins/zimaos/content/I18n.qml @@ -0,0 +1,86 @@ +pragma ComponentBehavior: Bound + +import QtQuick + +QtObject { + id: i18n + + readonly property string lang: { + var n = Qt.locale().name; + if (i18n.catalogs[n]) + return n; + var base = n.split("_")[0]; + return i18n.catalogs[base] ? base : "en"; + } + + readonly property var catalogs: ({ + "pt": { + "Go to Dashboard": "Ir ao painel", + "Open": "Abrir", + "Backup": "Backup", + "PeerDrop": "PeerDrop", + "System": "Sistema", + "CPU": "CPU", + "RAM": "RAM", + "Sign in": "Entrar", + "Sign out": "Sair", + "Username": "Utilizador", + "Password": "Palavra-passe", + "IP": "IP", + "Enter the ZimaOS address.": "Indique o endereço do ZimaOS.", + "That address is not valid. Use a hostname or IPv4, with an optional port.": "Endereço inválido. Use um nome ou IPv4, com porta opcional.", + "Enter the username and the password.": "Indique o utilizador e a palavra-passe.", + "Could not sign in.": "Não foi possível entrar.", + "Offline": "Sem resposta", + "Session expired": "Sessão expirada", + "Connecting": "A ligar", + "LAN": "LAN", + "Remote": "Remoto", + "Wi-Fi": "Wi-Fi", + "Ethernet": "Ethernet", + "Thunderbolt": "Thunderbolt", + "In use": "Em uso", + "Available": "Disponível", + "storage": "armazenamento" + }, + "pt_BR": { + "Go to Dashboard": "Ir ao painel", + "Open": "Abrir", + "Backup": "Backup", + "PeerDrop": "PeerDrop", + "System": "Sistema", + "CPU": "CPU", + "RAM": "RAM", + "Sign in": "Entrar", + "Sign out": "Sair", + "Username": "Usuário", + "Password": "Senha", + "IP": "IP", + "Enter the ZimaOS address.": "Informe o endereço do ZimaOS.", + "That address is not valid. Use a hostname or IPv4, with an optional port.": "Endereço inválido. Use um nome ou IPv4, com porta opcional.", + "Enter the username and the password.": "Informe o usuário e a senha.", + "Could not sign in.": "Não foi possível entrar.", + "Offline": "Sem resposta", + "Session expired": "Sessão expirada", + "Connecting": "Conectando", + "LAN": "LAN", + "Remote": "Remoto", + "Wi-Fi": "Wi-Fi", + "Ethernet": "Ethernet", + "Thunderbolt": "Thunderbolt", + "In use": "Em uso", + "Available": "Disponível", + "storage": "armazenamento" + } + }) + + function tr(s) { + if (s === undefined || s === null || s === "") + return s; + var map = i18n.catalogs[i18n.lang]; + if (!map) + return s; + var v = map["" + s]; + return v === undefined ? s : v; + } +} diff --git a/plugins/zimaos/content/Panel.qml b/plugins/zimaos/content/Panel.qml new file mode 100644 index 00000000..62547ccf --- /dev/null +++ b/plugins/zimaos/content/Panel.qml @@ -0,0 +1,684 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import QtQuick.Controls +import QtQuick.Shapes +import Ryoku.PluginKit +import Ryoku.PluginKit.Singletons + +// ZimaOS device card. Same facts as the Zima client card: name, link rates, +// address, dashboard, storage, backup, and PeerDrop. +Item { + id: root + + property var pluginApi + property string density: "full" + property real s: 1 + property real widthBudget: 380 + property bool active: false + + readonly property var service: pluginApi ? pluginApi.mainInstance : null + readonly property real w: widthBudget > 0 ? widthBudget : 380 + + implicitWidth: root.w + implicitHeight: col.implicitHeight + + I18n { id: i18n } + + property string formError: "" + + // The shell already draws the card: the same stroked glass as the + // now-playing panel. These are the chip tints that sit on it. + readonly property color ink: Theme.cream + readonly property color sumi: Theme.dim + readonly property color seal: Theme.accent + readonly property color sep: Theme.border + readonly property color fillIdle: Qt.rgba(0, 0, 0, 0.12) + readonly property color fillHover: Qt.rgba(Theme.accent.r, Theme.accent.g, Theme.accent.b, 0.10) + readonly property color fillActive: Theme.accent + + onActiveChanged: { + if (!root.active) { + passField.text = ""; + root.formError = ""; + } else { + root.fillAddress(); + } + } + + component Card: Rectangle { + property real pad: 12 + radius: 16 + color: root.fillIdle + border.width: 1 + border.color: root.sep + } + + // Gear and the PeerDrop person are not in the shell glyph set. + component LineIcon: Item { + id: mark + property string name: "" + property color color: Theme.iconDim + property real stroke: 1.6 + + readonly property var paths: ({ + "peer": "M10.4 8.3a2.2 2.2 0 1 1-4.4 0 2.2 2.2 0 0 1 4.4 0 M4.1 18c.6-2.6 2-3.9 4.1-3.9s3.5 1.3 4.1 3.9 M14.4 9.2a2.6 2.6 0 0 1 0 3.8 M16.6 7.1a5.4 5.4 0 0 1 0 8", + "globe": "M12 3.2a8.8 8.8 0 1 0 0 17.6 8.8 8.8 0 0 0 0-17.6z M3.2 12h17.6 M12 3.2c2.3 2.5 3.5 5.6 3.5 8.8s-1.2 6.3-3.5 8.8c-2.3-2.5-3.5-5.6-3.5-8.8s1.2-6.3 3.5-8.8z", + "bolt": "M13.2 2.8 6 13.2h5.2L10 21.2 18.4 10.2h-5.5z", + "gear": "M12 15.2a3.2 3.2 0 1 0 0-6.4 3.2 3.2 0 0 0 0 6.4z M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" + }) + readonly property string d: mark.paths[mark.name] !== undefined ? mark.paths[mark.name] : "" + readonly property real u: Math.min(width, height) / 24 + + Shape { + width: 24 + height: 24 + scale: mark.u + transformOrigin: Item.TopLeft + antialiasing: true + preferredRendererType: Shape.CurveRenderer + + ShapePath { + strokeColor: mark.color + fillColor: "transparent" + strokeWidth: mark.stroke + capStyle: ShapePath.RoundCap + joinStyle: ShapePath.RoundJoin + PathSvg { path: mark.d } + } + } + } + + // Remote, Wi-Fi, Ethernet, Thunderbolt. Accent is the path in use. + component PathMark: Item { + id: path + property string line: "" + property string glyph: "" + property string pathName: "" + property string title: "" + + readonly property string activeName: root.service ? root.service.linkActive : "" + readonly property bool onPath: path.activeName === path.pathName + || (path.activeName === "lan" && (path.pathName === "wifi" || path.pathName === "ethernet")) + readonly property bool up: { + if (!root.service) + return false; + if (path.pathName === "remote") + return root.service.linkRemote; + if (path.pathName === "wifi") + return root.service.linkWifi; + if (path.pathName === "ethernet") + return root.service.linkEthernet; + return root.service.linkThunderbolt; + } + + width: 14 * root.s + height: 14 * root.s + + LineIcon { + anchors.fill: parent + visible: path.line.length > 0 + name: path.line + color: path.onPath ? root.seal : (path.up ? root.ink : root.sumi) + opacity: path.onPath ? 1 : (path.up ? 0.85 : 0.34) + stroke: 1.6 + } + GlyphIcon { + anchors.fill: parent + visible: path.glyph.length > 0 + name: path.glyph + color: path.onPath ? root.seal : (path.up ? root.ink : root.sumi) + opacity: path.onPath ? 1 : (path.up ? 0.85 : 0.34) + stroke: 1.6 + } + + MouseArea { + id: pathHover + anchors.fill: parent + anchors.margins: -4 + hoverEnabled: true + acceptedButtons: Qt.NoButton + ToolTip.visible: pathHover.containsMouse + ToolTip.delay: 350 + ToolTip.text: { + var label = i18n.tr(path.title); + if (path.onPath) + return label + " · " + i18n.tr("In use"); + if (path.up) + return label + " · " + i18n.tr("Available"); + return label; + } + } + } + + Column { + id: col + width: root.w + spacing: 14 * root.s + + Item { + width: parent.width + implicitHeight: nameText.implicitHeight + + Text { + id: nameText + anchors.left: parent.left + anchors.right: logoutMark.left + anchors.rightMargin: 12 * root.s + text: { + if (!root.service || !root.service.authed) + return "ZimaOS"; + if (root.service.deviceName.length > 0) + return root.service.deviceName; + return root.service.online ? "ZimaOS" : i18n.tr("Offline"); + } + color: root.ink + font.family: Theme.mono + font.pixelSize: 18 * root.s + font.weight: Font.Medium + elide: Text.ElideRight + } + + GlyphIcon { + id: logoutMark + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + visible: root.service && root.service.authed + width: 16 * root.s + height: 16 * root.s + name: "logout" + color: logoutMa.containsMouse ? root.ink : root.sumi + stroke: 1.6 + + MouseArea { + id: logoutMa + anchors.fill: parent + anchors.margins: -8 + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: if (root.service) root.service.logout() + } + } + } + + Item { + visible: root.service && root.service.deviceImage.length > 0 + width: parent.width + implicitHeight: 148 * root.s + + Image { + anchors.centerIn: parent + width: Math.min(parent.width * 0.72, 210 * root.s) + height: 132 * root.s + source: root.service && root.service.deviceImage.length > 0 + ? ("file://" + root.service.deviceImage) : "" + fillMode: Image.PreserveAspectFit + asynchronous: true + cache: false + } + } + + Text { + visible: root.service && root.service.authed && root.service.errorText.length > 0 + width: parent.width + text: root.service ? root.service.errorText : "" + color: Theme.sun + font.family: Theme.mono + font.pixelSize: 11 * root.s + wrapMode: Text.WordWrap + } + + Column { + visible: root.service && root.service.authed + width: parent.width + spacing: 8 * root.s + + Item { + width: parent.width + implicitHeight: lanText.implicitHeight + + Text { + id: lanText + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + text: i18n.tr(root.service && root.service.ifaceLabel.length > 0 + ? root.service.ifaceLabel : "LAN") + color: root.ink + font.family: Theme.mono + font.pixelSize: 12 * root.s + font.weight: Font.Medium + } + + Row { + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + spacing: 10 * root.s + + PathMark { line: "globe"; pathName: "remote"; title: "Remote" } + PathMark { glyph: "wifi"; pathName: "wifi"; title: "Wi-Fi" } + PathMark { glyph: "reboot"; pathName: "ethernet"; title: "Ethernet" } + PathMark { line: "bolt"; pathName: "thunderbolt"; title: "Thunderbolt" } + } + } + + Item { + width: parent.width + implicitHeight: Math.max(ipText.implicitHeight, dashBtn.height) + + Text { + id: ipText + anchors.left: parent.left + anchors.right: dashBtn.left + anchors.rightMargin: 12 * root.s + anchors.verticalCenter: parent.verticalCenter + text: root.service && root.service.ipAddress.length > 0 ? root.service.ipAddress : "" + color: root.sumi + font.family: Theme.mono + font.pixelSize: 12 * root.s + elide: Text.ElideRight + } + + Rectangle { + id: dashBtn + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + width: dashLabel.implicitWidth + 16 * root.s + height: dashLabel.implicitHeight + 10 * root.s + radius: height / 2 + color: dashMa.containsMouse ? Theme.vermDeep : root.seal + border.width: 0 + + Text { + id: dashLabel + anchors.centerIn: parent + text: i18n.tr("Go to Dashboard") + color: Theme.cardBot + font.family: Theme.mono + font.pixelSize: 10 * root.s + font.weight: Font.Medium + font.letterSpacing: 0.4 + } + + MouseArea { + id: dashMa + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: root.openLink(root.service ? root.service.dashboardUrl : "") + } + } + } + } + + Card { + id: diskCard + visible: root.service && root.service.authed + width: parent.width + implicitHeight: 104 * root.s + color: diskMa.containsMouse ? root.fillHover : root.fillIdle + border.color: diskMa.containsMouse ? root.seal : root.sep + + Text { + anchors.left: parent.left + anchors.top: parent.top + anchors.right: folderMark.left + anchors.leftMargin: 16 * root.s + anchors.topMargin: 14 * root.s + anchors.rightMargin: 8 * root.s + text: i18n.tr("Open") + " " + (root.service && root.service.storageTitle.length > 0 + ? root.service.storageTitle + : i18n.tr("storage")) + color: root.ink + font.family: Theme.mono + font.pixelSize: 13 * root.s + font.weight: Font.Medium + elide: Text.ElideRight + } + + LineIcon { + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.leftMargin: 16 * root.s + anchors.bottomMargin: 14 * root.s + width: 18 * root.s + height: 18 * root.s + name: "gear" + color: root.sumi + stroke: 1.6 + } + + GlyphIcon { + id: folderMark + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.rightMargin: 18 * root.s + width: 36 * root.s + height: 36 * root.s + name: "folder" + color: diskMa.containsMouse ? root.ink : root.sumi + stroke: 1.5 + } + + MouseArea { + id: diskMa + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: root.openLink(root.service ? root.service.filesUrl : "") + } + } + + Row { + visible: root.service && root.service.authed + width: parent.width + spacing: 10 * root.s + + Card { + id: backupCard + width: (parent.width - parent.spacing) / 2 + implicitHeight: 108 * root.s + color: backupMa.containsMouse ? root.fillHover : root.fillIdle + border.color: backupMa.containsMouse ? root.seal : root.sep + + GlyphIcon { + x: 16 * root.s + y: 16 * root.s + width: 20 * root.s + height: 20 * root.s + name: "reboot" + color: backupMa.containsMouse ? root.ink : root.sumi + stroke: 1.6 + } + + Text { + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.leftMargin: 16 * root.s + anchors.bottomMargin: 14 * root.s + text: i18n.tr("Backup") + color: root.ink + font.family: Theme.mono + font.pixelSize: 12 * root.s + font.weight: Font.Medium + } + + MouseArea { + id: backupMa + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + if (!root.service) + return; + var url = root.service.backupUrl.length > 0 + ? root.service.backupUrl + : root.service.dashboardUrl; + root.openLink(url); + } + } + } + + Card { + id: peerCard + width: (parent.width - parent.spacing) / 2 + implicitHeight: 108 * root.s + color: peerMa.containsMouse ? root.fillHover : root.fillIdle + border.color: peerMa.containsMouse ? root.seal : root.sep + + LineIcon { + x: 16 * root.s + y: 16 * root.s + width: 20 * root.s + height: 20 * root.s + name: "peer" + color: peerMa.containsMouse ? root.ink : root.sumi + stroke: 1.6 + } + + Text { + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.leftMargin: 16 * root.s + anchors.bottomMargin: 14 * root.s + text: i18n.tr("PeerDrop") + color: root.ink + font.family: Theme.mono + font.pixelSize: 12 * root.s + font.weight: Font.Medium + } + + MouseArea { + id: peerMa + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: root.openLink(root.service ? root.service.peerDropUrl : "") + } + } + } + + Column { + width: parent.width + spacing: 8 * root.s + visible: root.service && !root.service.authed + + Text { + width: parent.width + text: { + if (root.formError.length > 0) + return root.formError; + if (!root.service) + return ""; + if (root.service.authError === "session expired") + return i18n.tr("Session expired"); + if (root.service.authError === "username and password are required") + return i18n.tr("Enter the username and the password."); + if (root.service.authError === "login failed" || root.service.authError === "invalid login payload") + return i18n.tr("Could not sign in."); + if (root.service.authError.length > 0) + return root.service.authError; + return root.service.errorText; + } + visible: text.length > 0 + color: Theme.sun + font.family: Theme.mono + font.pixelSize: 11 * root.s + wrapMode: Text.WordWrap + } + + Text { + text: i18n.tr("IP") + color: root.sumi + font.family: Theme.mono + font.pixelSize: 10 * root.s + font.letterSpacing: 1 + font.capitalization: Font.AllUppercase + } + + TextField { + id: ipField + width: parent.width + placeholderText: "192.168.0.180" + color: root.ink + placeholderTextColor: root.sumi + font.family: Theme.mono + font.pixelSize: 12 * root.s + padding: 8 * root.s + inputMethodHints: Qt.ImhNoPredictiveText | Qt.ImhNoAutoUppercase + background: Rectangle { + radius: 6 + color: root.fillIdle + border.width: 1 + border.color: ipField.activeFocus ? root.seal : root.sep + } + onAccepted: root.submitLogin() + } + + Text { + text: i18n.tr("Username") + color: root.sumi + font.family: Theme.mono + font.pixelSize: 10 * root.s + font.letterSpacing: 1 + font.capitalization: Font.AllUppercase + } + + TextField { + id: userField + width: parent.width + placeholderText: i18n.tr("Username") + color: root.ink + placeholderTextColor: root.sumi + font.family: Theme.mono + font.pixelSize: 12 * root.s + padding: 8 * root.s + background: Rectangle { + radius: 6 + color: root.fillIdle + border.width: 1 + border.color: userField.activeFocus ? root.seal : root.sep + } + } + + Text { + text: i18n.tr("Password") + color: root.sumi + font.family: Theme.mono + font.pixelSize: 10 * root.s + font.letterSpacing: 1 + font.capitalization: Font.AllUppercase + } + + TextField { + id: passField + width: parent.width + placeholderText: i18n.tr("Password") + echoMode: TextInput.Password + color: root.ink + placeholderTextColor: root.sumi + font.family: Theme.mono + font.pixelSize: 12 * root.s + padding: 8 * root.s + background: Rectangle { + radius: 6 + color: root.fillIdle + border.width: 1 + border.color: passField.activeFocus ? root.seal : root.sep + } + onAccepted: root.submitLogin() + } + + Rectangle { + width: parent.width + height: signLabel.implicitHeight + 12 * root.s + radius: 6 + color: signMa.containsMouse ? Theme.vermDeep : Theme.accent + border.width: 0 + + Text { + id: signLabel + anchors.centerIn: parent + text: root.service && root.service.busy ? i18n.tr("Connecting") : i18n.tr("Sign in") + color: Theme.cardBot + font.family: Theme.mono + font.pixelSize: 11 * root.s + font.weight: Font.Medium + font.letterSpacing: 1 + } + + MouseArea { + id: signMa + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: root.submitLogin() + } + } + } + + Row { + width: parent.width + visible: root.service && root.service.authed + spacing: 8 * root.s + + Text { + anchors.verticalCenter: parent.verticalCenter + width: parent.width - signOut.implicitWidth - 8 * root.s + text: root.service ? root.service.username : "" + color: root.sumi + font.family: Theme.mono + font.pixelSize: 10 * root.s + font.letterSpacing: 1 + elide: Text.ElideRight + } + + Text { + id: signOut + anchors.verticalCenter: parent.verticalCenter + text: i18n.tr("Sign out") + color: signOutMa.containsMouse ? root.ink : root.sumi + font.family: Theme.mono + font.pixelSize: 10 * root.s + font.letterSpacing: 1 + + MouseArea { + id: signOutMa + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + passField.text = ""; + if (root.service) + root.service.logout(); + } + } + } + } + } + + readonly property string watchedHost: root.service && root.service.host ? root.service.host : "" + readonly property string watchedUser: root.service && root.service.username ? root.service.username : "" + onWatchedHostChanged: root.fillAddress() + onWatchedUserChanged: { + if (userField.text.length === 0 && root.watchedUser.length > 0) + userField.text = root.watchedUser; + } + + function openLink(url) { + if (!root.service || !url) + return; + if (url.indexOf("http://") !== 0 && url.indexOf("https://") !== 0) + return; + root.service.openUrl(url); + if (root.pluginApi) + root.pluginApi.closePanel(); + } + + function fillAddress() { + if (ipField.text.length === 0 && root.service && root.service.host.length > 0) + ipField.text = root.service.host; + } + + function submitLogin() { + if (!root.service || root.service.busy) + return; + var addr = ipField.text.trim(); + if (addr.length === 0) { + root.formError = i18n.tr("Enter the ZimaOS address."); + return; + } + if (root.service.normalizeHost(addr) === "") { + root.formError = i18n.tr("That address is not valid. Use a hostname or IPv4, with an optional port."); + return; + } + if (userField.text.trim().length === 0 || passField.text.length === 0) { + root.formError = i18n.tr("Enter the username and the password."); + return; + } + root.formError = ""; + if (!root.service.useHost(addr)) + return; + root.service.login(userField.text.trim(), passField.text); + passField.text = ""; + } +} diff --git a/plugins/zimaos/content/Widget.qml b/plugins/zimaos/content/Widget.qml new file mode 100644 index 00000000..cd13ea61 --- /dev/null +++ b/plugins/zimaos/content/Widget.qml @@ -0,0 +1,83 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import QtQuick.Effects +import Ryoku.PluginKit +import Ryoku.PluginKit.Singletons + +// Bar glyph. A click only opens the ZimaOS card. +Item { + id: root + + property var pluginApi + property var screen + property bool active: false + property string density: "glyph" + property real s: 1 + property real widthBudget: 0 + property bool open: false + property real reveal: 0 + property bool tabActive: false + signal requestClose() + + readonly property var service: pluginApi ? pluginApi.mainInstance : null + readonly property bool panelOpen: pluginApi ? pluginApi.panelOpen : false + readonly property bool online: service ? service.online : false + readonly property bool lit: root.panelOpen || hover.hovered + + implicitWidth: 22 * root.s + implicitHeight: 22 * root.s + + Rectangle { + anchors.centerIn: parent + width: 20 * root.s + height: 20 * root.s + radius: 0 + color: root.lit ? Theme.sheen : "transparent" + border.width: root.panelOpen ? 1 : 0 + border.color: Theme.hair + Behavior on color { ColorAnimation { duration: 120 } } + } + + Item { + id: markBox + anchors.centerIn: parent + width: 16 * root.s + height: 16 * root.s + + Image { + id: mark + anchors.fill: parent + source: Qt.resolvedUrl("zima-mark.png") + fillMode: Image.PreserveAspectFit + smooth: true + mipmap: true + visible: false + } + + MultiEffect { + anchors.fill: parent + source: mark + colorization: 1 + colorizationColor: root.panelOpen ? Theme.cream : (hover.hovered ? Theme.cream : Theme.iconDim) + opacity: root.online || root.panelOpen ? 1 : 0.45 + Behavior on opacity { NumberAnimation { duration: 120 } } + } + } + + HoverHandler { + id: hover + cursorShape: Qt.PointingHandCursor + } + + TapHandler { + onTapped: { + if (!root.pluginApi) + return; + if (root.open) + root.requestClose(); + else if (root.pluginApi.togglePanel) + root.pluginApi.togglePanel(); + } + } +} diff --git a/plugins/zimaos/content/zima-mark.png b/plugins/zimaos/content/zima-mark.png new file mode 100644 index 0000000000000000000000000000000000000000..6093ac9444c820a3b73d20ccd06b974d618d985b GIT binary patch literal 6014 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", + "description": "QS Bar card for a ZimaOS server: device name, link rate, storage, and a shortcut to the dashboard.", + "license": "MIT", + "upstream": "https://github.com/leandrofelix-dev/ryoku-zima-client", + "official": false, + "tags": [ + "zimaos", + "nas", + "bar-widget" + ], + "hosts": [ + "topbarGlyph" + ], + "entryPoints": { + "main": "service/Main.qml", + "content": "content/Widget.qml", + "panel": "content/Panel.qml" + }, + "panel": { + "width": 380 + }, + "files": [ + "content/I18n.qml", + "bin/zima", + "assets/preview-widget.png", + "content/zima-mark.png" + ], + "capabilities": { + "densities": [ + "glyph", + "full" + ], + "network": [] + }, + "defaults": { + "host": "topbarGlyph", + "icon": "archive", + "label": "ZimaOS", + "bar": { + "section": "right" + } + }, + "dependencies": { + "commands": [ + "python3", + "xdg-open" + ] + }, + "metadata": { + "settings": [ + { + "key": "host", + "type": "text", + "label": "ZimaOS address", + "group": "ZimaOS", + "default": "", + "placeholder": "192.168.0.180" + }, + { + "key": "poll", + "type": "int", + "label": "Refresh seconds", + "group": "ZimaOS", + "default": 8, + "min": 3, + "max": 60 + } + ] + } +} diff --git a/plugins/zimaos/product-manifest.json b/plugins/zimaos/product-manifest.json new file mode 100644 index 00000000..67bd8e3d --- /dev/null +++ b/plugins/zimaos/product-manifest.json @@ -0,0 +1,113 @@ +{ + "schema": 1, + "id": "zimaos", + "category": "plugins", + "version": "0.1.16", + "destination": "ryoku/plugins/zimaos", + "files": [ + { + "source": ".gitignore", + "destination": ".gitignore", + "sha256": "6b9f20b26bcd5a7db7411faba95d63155e7a096902e18b9de8e4d9876ddba6ee", + "mode": "0644", + "size": 41, + "install": true + }, + { + "source": "AGENTS.md", + "destination": "AGENTS.md", + "sha256": "e311f126eec8ad68644db0704a6ba815d915f90ab8dcf537d58a90df1c06a5da", + "mode": "0644", + "size": 4625, + "install": true + }, + { + "source": "CLAUDE.md", + "destination": "CLAUDE.md", + "sha256": "09ffb8ebdb8adf50bf4bde26dfe2109b4af3a4a8cc3f30cc536be42bb912c033", + "mode": "0644", + "size": 152, + "install": true + }, + { + "source": "LICENSE", + "destination": "LICENSE", + "sha256": "97483adbcfff65229fdf21ea76178690f1bfe3ccd5fbde97e344e04d625dc4bd", + "mode": "0644", + "size": 1062, + "install": true + }, + { + "source": "README.md", + "destination": "README.md", + "sha256": "effedc9bd5ab9b8a75596923bd23a59e1ba8b8679132a1d65d1503144d3afb55", + "mode": "0644", + "size": 3215, + "install": false + }, + { + "source": "assets/preview-widget.png", + "destination": "assets/preview-widget.png", + "sha256": "8a91b27c6503c5a750b00784b3d1e0652e28c244fa6da11c2945e41172991e87", + "mode": "0644", + "size": 161842, + "install": false + }, + { + "source": "bin/zima", + "destination": "bin/zima", + "sha256": "eaeab05fd5f39c6dc7ff20023745269346c67f9051c5e79f988de62e709c72c9", + "mode": "0755", + "size": 26747, + "install": true + }, + { + "source": "content/I18n.qml", + "destination": "content/I18n.qml", + "sha256": "74ff808ff4ef20ca385e9bbd72ef4ae003751f9801482e96d93404ead611111c", + "mode": "0644", + "size": 3013, + "install": true + }, + { + "source": "content/Panel.qml", + "destination": "content/Panel.qml", + "sha256": "9f2973be4b64ce1b6dc216ddc6ed3b9c9f208fdd614be266e997a88733ca7496", + "mode": "0644", + "size": 25417, + "install": true + }, + { + "source": "content/Widget.qml", + "destination": "content/Widget.qml", + "sha256": "6ec38de78f22de1fc528cdd16df076f1b2d8b4c1c094e740378c68937be02c01", + "mode": "0644", + "size": 2271, + "install": true + }, + { + "source": "content/zima-mark.png", + "destination": "content/zima-mark.png", + "sha256": "e67752d7533cee5453c398ca5aaf19ee25e17c4b36f5896904d771623997cd70", + "mode": "0644", + "size": 6014, + "install": true + }, + { + "source": "manifest.json", + "destination": "manifest.json", + "sha256": "8f73fc3b4d69c94b9ac7cd45b5e2715b30ce881d57d082d95aa7694c936a412f", + "mode": "0644", + "size": 1450, + "install": true + }, + { + "source": "service/Main.qml", + "destination": "service/Main.qml", + "sha256": "e99ad7e8e128450a7b072a8bbb4cb2c4ccfc10cfb69c752a63c88f62713e25ef", + "mode": "0644", + "size": 17806, + "install": true + } + ] +} diff --git a/plugins/zimaos/service/Main.qml b/plugins/zimaos/service/Main.qml new file mode 100644 index 00000000..0bc25b79 --- /dev/null +++ b/plugins/zimaos/service/Main.qml @@ -0,0 +1,509 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import Quickshell +import Quickshell.Io + +// One ZimaOS box. Public device info needs no login. Network rates, the +// storage pool and CPU/RAM come from the same calls the ZimaOS dashboard makes, +// after a session written only under pluginApi.stateDir. +Item { + id: svc + + property var pluginApi + readonly property var settings: pluginApi ? pluginApi.pluginSettings : null + + // Typed on the login screen, then saved. Empty until the user sets one. + property string activeHost: "" + readonly property string savedHost: { + var raw = settings && settings.host !== undefined && settings.host !== null + ? ("" + settings.host).trim() : ""; + return raw; + } + readonly property string host: svc.activeHost.length > 0 ? svc.activeHost : svc.savedHost + readonly property bool hostReady: svc.normalizeHost(svc.host).length > 0 + readonly property int pollSec: { + var n = settings && settings.poll !== undefined ? Number(settings.poll) : 8; + if (!isFinite(n)) + return 8; + return Math.max(3, Math.min(60, Math.round(n))); + } + readonly property string binPath: pluginApi && pluginApi.pluginDir + ? pluginApi.pluginDir + "/bin/zima" : "" + readonly property string stateFile: pluginApi && pluginApi.stateDir + ? pluginApi.stateDir + "/session.json" : "" + + property bool online: false + property bool authed: false + property bool busy: false + property string errorText: "" + property string authError: "" + property string username: "" + property string deviceName: "" + property string osVersion: "" + property string deviceModel: "" + property string cpuModel: "" + property real memoryBytes: -1 + property real cpuPercent: -1 + property real memPercent: -1 + property string ifaceLabel: "LAN" + property string ipAddress: "" + property bool linkRemote: false + property bool linkWifi: false + property bool linkEthernet: false + property bool linkThunderbolt: false + property string linkActive: "" + property real downBps: 0 + property real upBps: 0 + property string storageName: "" + property real storageTotal: -1 + property real storageUsed: -1 + property real storageAvail: -1 + property string dashboardUrl: "" + property string filesUrl: "" + property string backupUrl: "" + property string peerDropUrl: "" + property string deviceImage: "" + + property real _prevSent: -1 + property real _prevRecv: -1 + property real _prevStamp: -1 + property var _queue: [] + property bool _statusAfterLogin: false + property bool _statusAgain: false + + function formatBytes(n) { + if (n === undefined || n === null || !isFinite(n) || n < 0) + return ""; + var units = ["B", "KB", "MB", "GB", "TB"]; + var v = n; + var i = 0; + while (v >= 1024 && i < units.length - 1) { + v /= 1024; + i++; + } + var digits = (i === 0 || v >= 100) ? 0 : (v >= 10 ? 1 : 2); + return v.toFixed(digits) + " " + units[i]; + } + + function formatRate(bps) { + if (!isFinite(bps) || bps < 1) + return "0 B"; + return svc.formatBytes(bps); + } + + readonly property string downText: svc.authed ? svc.formatRate(svc.downBps) : "—" + readonly property string upText: svc.authed ? svc.formatRate(svc.upBps) : "—" + readonly property string cpuText: svc.cpuPercent >= 0 ? Math.round(svc.cpuPercent) + "%" : "—" + readonly property string ramText: svc.memPercent >= 0 + ? Math.round(svc.memPercent) + "%" + : (svc.memoryBytes > 0 ? svc.formatBytes(svc.memoryBytes) : "—") + readonly property string storageTitle: svc.storageName.length > 0 ? svc.storageName : "" + readonly property string storageLine: { + if (svc.storageAvail >= 0 && svc.storageTotal >= 0) + return svc.formatBytes(svc.storageAvail) + " · " + svc.formatBytes(svc.storageTotal); + if (svc.storageTotal >= 0) + return svc.formatBytes(svc.storageTotal); + return ""; + } + readonly property real storageFraction: { + if (svc.storageTotal <= 0 || svc.storageUsed < 0) + return 0; + return Math.max(0, Math.min(1, svc.storageUsed / svc.storageTotal)); + } + + function enqueue(op) { + var next = svc._queue.slice(); + next.push(op); + svc._queue = next; + svc.pump(); + } + + function pump() { + if (proc.running || svc._queue.length === 0 || svc.binPath === "") + return; + var op = svc._queue[0]; + svc._queue = svc._queue.slice(1); + proc.opKind = op.kind; + proc.opHost = op.host || ""; + proc.payload = op.payload || ""; + proc.command = op.command; + proc.running = true; + } + + function normalizeHost(raw) { + var text = (raw || "").trim(); + // Bare LAN addresses stay http on the Python side. https:// is kept so + // that call verifies the certificate. http:// is stored without a scheme + // so an existing session for the same host still matches. + var scheme = ""; + var lower = text.toLowerCase(); + if (lower.indexOf("https://") === 0) { + scheme = "https"; + text = text.substring(8); + } else if (lower.indexOf("http://") === 0) { + scheme = "http"; + text = text.substring(7); + } + if (text.length === 0 || text.indexOf("@") >= 0 || text.indexOf("://") >= 0 + || text.indexOf("/") >= 0 || text.indexOf("\\") >= 0 || text.indexOf(" ") >= 0) + return ""; + var host = text; + var port = ""; + if (host.charAt(0) === "[") { + var end = host.indexOf("]"); + if (end < 0) + return ""; + port = host.substring(end + 1); + host = host.substring(0, end + 1); + if (port.charAt(0) === ":") + port = port.substring(1); + else if (port.length > 0) + return ""; + } else { + var pieces = host.split(":"); + if (pieces.length === 2) { + host = pieces[0]; + port = pieces[1]; + } else if (pieces.length > 2) { + return ""; + } + } + var ipv4 = /^(?:\d{1,3}\.){3}\d{1,3}$/.test(host); + var name = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/.test(host); + if (ipv4) { + var nums = host.split("."); + for (var i = 0; i < nums.length; ++i) { + if (Number(nums[i]) > 255) + return ""; + } + } else if (!name) { + return ""; + } + if (port.length > 0) { + if (!/^\d{1,5}$/.test(port)) + return ""; + var n = Number(port); + if (n < 1 || n > 65535) + return ""; + return scheme === "https" ? ("https://" + host + ":" + n) : (host + ":" + n); + } + return scheme === "https" ? ("https://" + host) : host; + } + + function useHost(raw) { + var clean = svc.normalizeHost(raw); + if (clean === "") + return false; + svc.activeHost = clean; + if (svc.pluginApi && svc.savedHost !== clean) + svc.pluginApi.saveSetting("host", clean); + return true; + } + + function statusOp() { + return { + kind: "status", + host: svc.host, + command: [svc.binPath, "status", svc.host, svc.stateFile] + }; + } + + function refresh() { + if (!svc.hostReady || svc.binPath === "" || svc.stateFile === "") + return; + // A status already running for another host must not swallow this + // refresh. Its result is ignored, then this host is fetched. + if (proc.running && proc.opKind === "status") { + if (proc.opHost !== svc.host) + svc._statusAgain = true; + return; + } + var kept = []; + var hasCurrent = false; + for (var i = 0; i < svc._queue.length; i++) { + var item = svc._queue[i]; + if (item.kind === "status") { + if (item.host === svc.host && !hasCurrent) { + kept.push(item); + hasCurrent = true; + } + continue; + } + kept.push(item); + } + svc._queue = kept; + if (hasCurrent) + return; + svc.enqueue(svc.statusOp()); + } + + // useHost() starts a status poll before login() is queued. That poll, or + // one already sitting in the queue, used to make the post-login refresh() + // return early, so the sign-in form stayed up until the next timer tick. + function refreshAfterLogin() { + if (!svc.hostReady || svc.binPath === "" || svc.stateFile === "") + return; + var kept = []; + for (var i = 0; i < svc._queue.length; i++) { + if (svc._queue[i].kind !== "status") + kept.push(svc._queue[i]); + } + svc._queue = kept; + if (proc.running && proc.opKind === "status") { + svc._statusAfterLogin = true; + return; + } + svc._statusAfterLogin = false; + svc.enqueue(svc.statusOp()); + } + + function takeLoginStatus() { + if (!svc._statusAfterLogin) + return; + svc._statusAfterLogin = false; + svc.enqueue(svc.statusOp()); + } + + function login(username, password) { + if (!svc.hostReady || svc.binPath === "" || svc.stateFile === "") + return; + svc.busy = true; + svc.authError = ""; + svc.enqueue({ + kind: "login", + payload: JSON.stringify({ username: username, password: password }), + command: [svc.binPath, "login", svc.host, svc.stateFile] + }); + } + + function logout() { + if (svc.binPath === "" || svc.stateFile === "") + return; + svc.enqueue({ + kind: "logout", + command: [svc.binPath, "logout", svc.stateFile] + }); + } + + function openUrl(url) { + if (!url) + return; + if (url.indexOf("http://") !== 0 && url.indexOf("https://") !== 0) + return; + Quickshell.execDetached(["xdg-open", url]); + } + + function num(value) { + if (value === null || value === undefined) + return -1; + var n = Number(value); + return isFinite(n) ? n : -1; + } + + function noteRates(sent, recv, stamp) { + var now = Date.now() / 1000; + var mark = (stamp !== null && stamp !== undefined && isFinite(Number(stamp)) && Number(stamp) > 0) + ? Number(stamp) : now; + if (svc._prevStamp > 0 && sent >= 0 && recv >= 0 && svc._prevSent >= 0) { + var dt = mark - svc._prevStamp; + if (dt <= 0 || dt > 120) + dt = now - svc._prevWall; + if (dt > 0 && dt < 120) { + svc.upBps = Math.max(0, (sent - svc._prevSent) / dt); + svc.downBps = Math.max(0, (recv - svc._prevRecv) / dt); + } + } + svc._prevSent = sent; + svc._prevRecv = recv; + svc._prevStamp = mark; + svc._prevWall = now; + } + + property real _prevWall: 0 + + function applyStatus(parsed) { + if (!parsed || parsed.ok !== true) { + svc.online = false; + svc.errorText = parsed && parsed.error ? ("" + parsed.error) : "offline"; + return; + } + svc.online = true; + svc.errorText = ""; + svc.authError = parsed.authError ? ("" + parsed.authError) : ""; + svc.authed = parsed.authed === true; + svc.username = parsed.username ? ("" + parsed.username) : ""; + svc.deviceName = parsed.deviceName ? ("" + parsed.deviceName) : ""; + svc.osVersion = parsed.osVersion ? ("" + parsed.osVersion) : ""; + svc.deviceModel = parsed.deviceModel ? ("" + parsed.deviceModel) : ""; + svc.cpuModel = parsed.cpuModel ? ("" + parsed.cpuModel) : ""; + svc.memoryBytes = svc.num(parsed.memoryBytes); + svc.dashboardUrl = parsed.dashboardUrl ? ("" + parsed.dashboardUrl) : ""; + svc.filesUrl = parsed.filesUrl ? ("" + parsed.filesUrl) : ""; + svc.backupUrl = parsed.backupUrl ? ("" + parsed.backupUrl) : ""; + svc.peerDropUrl = parsed.peerDropUrl ? ("" + parsed.peerDropUrl) : ""; + if (parsed.deviceImage) + svc.deviceImage = "" + parsed.deviceImage; + if (!svc.authed) { + svc.cpuPercent = -1; + svc.memPercent = -1; + svc.downBps = 0; + svc.upBps = 0; + svc._prevStamp = -1; + svc.storageName = ""; + svc.storageTotal = -1; + svc.storageUsed = -1; + svc.storageAvail = -1; + svc.ifaceLabel = "LAN"; + svc.ipAddress = svc.host; + svc.linkRemote = false; + svc.linkWifi = false; + svc.linkEthernet = false; + svc.linkThunderbolt = false; + svc.linkActive = ""; + return; + } + svc.cpuPercent = svc.num(parsed.cpuPercent); + svc.memPercent = svc.num(parsed.memPercent); + var net = parsed.network || {}; + svc.ifaceLabel = net.label ? ("" + net.label) : "LAN"; + svc.ipAddress = net.ip ? ("" + net.ip) : svc.host; + svc.linkRemote = net.remote === true; + svc.linkWifi = net.wifi === true; + svc.linkEthernet = net.ethernet === true; + svc.linkThunderbolt = net.thunderbolt === true; + svc.linkActive = net.active ? ("" + net.active) : ""; + svc.noteRates(svc.num(net.bytesSent), svc.num(net.bytesRecv), net.time); + var disk = parsed.storage || null; + if (disk) { + svc.storageName = disk.name ? ("" + disk.name) : ""; + svc.storageTotal = svc.num(disk.total); + svc.storageUsed = svc.num(disk.used); + svc.storageAvail = svc.num(disk.avail); + } else { + svc.storageName = ""; + svc.storageTotal = -1; + svc.storageUsed = -1; + svc.storageAvail = -1; + } + } + + function applyResult(kind, text) { + var parsed = null; + try { + parsed = JSON.parse((text || "").trim()); + } catch (e) { + parsed = { ok: false, error: "bad response" }; + } + if (kind === "status") { + // Drop a result fetched for a host that is no longer active, or the + // panel keeps the previous server after the address changes. + if (proc.opHost === svc.host) { + svc.applyStatus(parsed); + svc._statusAgain = false; + } else { + svc._statusAgain = true; + } + svc.takeLoginStatus(); + if (svc._statusAgain) { + svc._statusAgain = false; + svc.refresh(); + } + } else if (kind === "login") { + svc.busy = false; + if (parsed && parsed.ok === true) { + svc.authError = ""; + svc.refreshAfterLogin(); + } else { + svc.authError = parsed && parsed.error ? ("" + parsed.error) : "login failed"; + } + } else if (kind === "logout") { + svc.authed = false; + svc.username = ""; + svc.authError = ""; + svc.cpuPercent = -1; + svc.memPercent = -1; + svc.downBps = 0; + svc.upBps = 0; + svc._prevStamp = -1; + svc.storageName = ""; + svc.linkRemote = false; + svc.linkWifi = false; + svc.linkEthernet = false; + svc.linkThunderbolt = false; + svc.linkActive = ""; + svc.refresh(); + } + } + + onHostChanged: { + svc._prevStamp = -1; + svc.downBps = 0; + svc.upBps = 0; + svc.online = false; + svc.authed = false; + svc.deviceName = ""; + svc.osVersion = ""; + svc.deviceModel = ""; + svc.deviceImage = ""; + svc.dashboardUrl = ""; + svc.filesUrl = ""; + svc.backupUrl = ""; + svc.peerDropUrl = ""; + svc.username = ""; + svc.authError = ""; + svc.errorText = ""; + svc.ipAddress = ""; + svc.storageName = ""; + svc.storageTotal = -1; + svc.storageUsed = -1; + svc.storageAvail = -1; + if (!svc.hostReady) + return; + svc.refresh(); + } + + Timer { + interval: svc.pollSec * 1000 + repeat: true + running: svc.hostReady && svc.binPath !== "" && svc.stateFile !== "" + triggeredOnStart: true + onTriggered: svc.refresh() + } + + Process { + id: proc + running: false + property string opKind: "" + property string opHost: "" + property string payload: "" + property bool outputSeen: false + + onRunningChanged: { + if (!proc.running) + return; + proc.outputSeen = false; + proc.stdinEnabled = true; + if (proc.payload.length > 0) + proc.write(proc.payload); + proc.payload = ""; + proc.stdinEnabled = false; + } + + stdout: StdioCollector { + id: out + onStreamFinished: { + proc.outputSeen = true; + svc.applyResult(proc.opKind, out.text); + } + } + + onExited: { + if (!proc.outputSeen) + svc.applyResult(proc.opKind, out.text); + else if (proc.opKind === "status") + svc.takeLoginStatus(); + Qt.callLater(svc.pump); + } + } +} From c1ed98d203ebd5c7fc31a360d5d1cfef05bc3f90 Mon Sep 17 00:00:00 2001 From: Leandro Felix Date: Mon, 9 Nov 2026 11:37:18 -0300 Subject: [PATCH 2/2] plugins: name the ZimaOS upstream repository The catalogue screen requires an https project URL, and plugin share does not copy one into the registry entry. --- plugins/registry.json | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/registry.json b/plugins/registry.json index 06d7277f..403b1816 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -1388,6 +1388,7 @@ "version": "0.1.16", "path": "plugins/zimaos", "author": "Felix ", + "upstream": "https://github.com/leandrofelix-dev/ryoku-zima-client", "summary": "QS Bar card for a ZimaOS server: device name, link rate, storage, and a shortcut to the dashboard.", "description": "QS Bar card for a ZimaOS server: device name, link rate, storage, and a shortcut to the dashboard.", "tags": [