Convert neohtop to Extension
neohtop is a beautiful desktop version of the htop command.
A modern, cross-platform system monitor built on top of Svelte, Rust, and Tauri.
In this blog, I will talk about how I converted neohtop to an extension.
It maybe simpler than you think.
TC;SC
- A demo PR: https://github.com/kunkunsh/kunkun-ext-neohtop/pull/1/files
- The extension: https://kunkun.sh/store/neohtop
- The repo: https://github.com/kunkunsh/kunkun-ext-neohtop
Here is a screenshot of the extension, exactly the same as the desktop version.
Intro
neohtop is a Tauri app. It’s frontend is built with Svelte, and backend is built with Rust.
One of the reasons I created kunkun is to make it easy to write cross-platform apps and distribute them on different platforms.
And neohtop is a perfect example for this.
It’s a nice GUI wrapper over the sysinfo
crate.
See its Cargo.toml.
Luckily, Kunkun’s extension API also provides a sysInfo
API, see docs.
It is based on tauri-plugin-system-info, which is also a wrapper over the sysinfo
crate. See Cargo.toml.
Since the data source are the same, then it should be straightforward to convert it to an extension.
I set a 30 minutes goal for myself, but it took me 90 minutes to complete the conversion.
This is because neohtop
did its data aggregation and preprocessing in rust, and I need to convert the logic to TypeScript.
Kind of like how TypeScript is converted to Golang, I just needed to convert the rust code to TypeScript, not hard at all, just time-consuming.
Code
In this PR, I demonstrated all the changes I made for the conversion.
First of all, neohtop is written in frontend framework svelte, so obviously this is a custom UI extension.
Manifest
"kunkun": { "name": "neohtop", "shortDescription": "A modern, cross-platform system monitor", "longDescription": "A modern, cross-platform system monitor", "identifier": "neohtop", "demoImages": [ "https://imgur.com/D8VHDEz.png" ], "permissions": [ "system-info:all", "shell:kill-any" ], "icon": { "type": "remote-url", "value": "https://github.com/Abdenasser/neohtop/raw/main/app-icon.png" }, "customUiCmds": [ { "name": "neohtop", "main": "/", "dist": "build", "devMain": "http://localhost:1420", "cmds": [], "window": { "title": "Neohtop", "hiddenTitle": true, "titleBarStyle": "overlay", "width": 1400, "height": 1000 } } ]},
build
folder is the default output folder of svelte projects, thusdist
is set tobuild
.devMain
is the local server that serves the svelte project, it is used when developing the extension with HMR.system-info:all
permission is required to access the system info data.shell:kill-any
permission is required to kill any process by apid
.
Frontend
neohtop has no default window title bar, but users can drag the window by clicking on the top of the app.
This is achieved by simply including data-tauri-drag-region
in a div
element.
<div class="title-bar" data-tauri-drag-region></div>
In a KK extension, we use data-kunkun-drag-region
instead, just remember to call ui.registerDragRegion
in app initialization.
<div class="title-bar" data-tauri-drag-region><div class="title-bar" data-kunkun-drag-region>
import { ui } from "@kksh/api/ui/custom";onMount(() => { ui.registerDragRegion("kunkun");});
Data Preprocessing/Aggregation
This is the most time-consuming part.
The source system info data is preprocessed before rendering. The preprocessing logic is written in Rust, thus I need to convert them to TypeScript.
neohtop (Rust) | kunkun-ext-neohtop (TypeScript) |
---|---|
process_monitor.rs | processMonitor.ts |
system_monitor.rs | systemMonitor.ts |
Acknowledgements
- Abdenasser for the awesome neohtop