api deserialization, sidebars

This commit is contained in:
Margret Riegert
2026-03-20 02:43:24 -04:00
parent 505cc110aa
commit bdeda666c1
7 changed files with 265 additions and 21 deletions

147
Cargo.lock generated
View File

@@ -1238,8 +1238,11 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
name = "ermine"
version = "0.1.0"
dependencies = [
"serde",
"serde_json",
"slint",
"slint-build",
"ureq",
]
[[package]]
@@ -1653,6 +1656,17 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "getrandom"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "getrandom"
version = "0.3.4"
@@ -1866,6 +1880,22 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48ce8546b993eaf241d69ded33b1be6d205dd9857ec879d9d18bd05d3676e144"
[[package]]
name = "http"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"
dependencies = [
"bytes",
"itoa",
]
[[package]]
name = "httparse"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
[[package]]
name = "i-slint-backend-linuxkms"
version = "1.15.1"
@@ -3811,6 +3841,20 @@ dependencies = [
"bytemuck",
]
[[package]]
name = "ring"
version = "0.17.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
dependencies = [
"cc",
"cfg-if",
"getrandom 0.2.17",
"libc",
"untrusted",
"windows-sys 0.52.0",
]
[[package]]
name = "rowan"
version = "0.16.1"
@@ -3892,6 +3936,41 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "rustls"
version = "0.23.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4"
dependencies = [
"log",
"once_cell",
"ring",
"rustls-pki-types",
"rustls-webpki",
"subtle",
"zeroize",
]
[[package]]
name = "rustls-pki-types"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd"
dependencies = [
"zeroize",
]
[[package]]
name = "rustls-webpki"
version = "0.103.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53"
dependencies = [
"ring",
"rustls-pki-types",
"untrusted",
]
[[package]]
name = "rustversion"
version = "1.0.22"
@@ -4362,6 +4441,12 @@ dependencies = [
"syn",
]
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "svgtypes"
version = "0.16.1"
@@ -4782,12 +4867,47 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "unty"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
[[package]]
name = "ureq"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdc97a28575b85cfedf2a7e7d3cc64b3e11bd8ac766666318003abbacc7a21fc"
dependencies = [
"base64",
"flate2",
"log",
"percent-encoding",
"rustls",
"rustls-pki-types",
"ureq-proto",
"utf-8",
"webpki-roots",
]
[[package]]
name = "ureq-proto"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f"
dependencies = [
"base64",
"http",
"httparse",
"log",
]
[[package]]
name = "url"
version = "2.5.8"
@@ -4827,6 +4947,12 @@ dependencies = [
"xmlwriter",
]
[[package]]
name = "utf-8"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "utf8_iter"
version = "1.0.4"
@@ -4894,6 +5020,12 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasip2"
version = "1.0.2+wasi-0.2.9"
@@ -5160,6 +5292,15 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "webpki-roots"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "weezl"
version = "0.1.12"
@@ -6215,6 +6356,12 @@ dependencies = [
"synstructure",
]
[[package]]
name = "zeroize"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
[[package]]
name = "zerotrie"
version = "0.2.3"

View File

@@ -6,7 +6,10 @@ version = "0.1.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = {version = "1.0.149", features = ["derive"]}
serde_json = "1.0.149"
slint = "1.14.1"
ureq = "3.2.0"
[build-dependencies]
slint-build = "1.14.1"

View File

@@ -61,3 +61,10 @@ Notes:
- Trying to use progenitor + openAPI spec to generate rust code, not going that well, and Gwen said it may be better to write these by hand
- progenitor didn't work due to it operating under the assumption that endpoints only return one type, which this spec violates (https://github.com/oxidecomputer/progenitor/issues/950)
- Read through documentation mostly, taking it slow and making sure I understand how things are working, being patient with myself
# 2026-03-20
## 0220
Figured the API endpoint (`/api`) would be a good place to start. Now have successful deserialization.
Sidebars are important, so I added two, one for channel list and another for server list. I'm still trying to figure out the best way to integrate different instances seamlessly.

32
src/api.rs Normal file
View File

@@ -0,0 +1,32 @@
#[derive(serde::Deserialize, Debug)]
pub struct ServerInfo {
// version number
revolt: String,
// main websocket
ws: String,
// main app URL
app: String,
vapid: String,
features: ServerFeatures,
}
#[derive(serde::Deserialize, Debug)]
struct ServerFeatures {
email: bool,
invite_only: bool,
// file server
autumn: Option<ServerFeatureEndpoint>,
// media server
january: Option<ServerFeatureEndpoint>,
//
voso: Option<ServerFeatureEndpoint>,
// voip server
livekit: Option<ServerFeatureEndpoint>,
}
#[derive(serde::Deserialize, Debug)]
struct ServerFeatureEndpoint {
enabled: bool,
url: Option<String>,
ws: Option<String>,
}

View File

@@ -2,10 +2,20 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use std::error::Error;
mod api;
slint::include_modules!();
fn main() -> Result<(), Box<dyn Error>> {
let response = ureq::get("https://revolt.handmadecities.com/api")
.call()?
.body_mut()
.read_to_string()?;
let server_info: api::ServerInfo = serde_json::from_str(&response).unwrap();
println!("{:#?}", server_info);
let ui = AppWindow::new()?;
// ui.on_request_increase_value({

View File

@@ -1,7 +1,24 @@
import { Button, VerticalBox, TextEdit } from "std-widgets.slint";
import { ChatView } from "chat-view.slint";
import { ChannelSidebar, ServerSidebar } from "sidebar.slint";
export component AppWindow inherits Window {
title: "ermine";
property <bool> sidebar-open: true;
HorizontalLayout {
ServerSidebar {
open: root.width > 600px;
server_list: [{ icon: "😳" }, { icon: "😍" }];
background: yellow;
}
ChannelSidebar {
open: root.width > 600px ? sidebar-open : false;
channel_list: [{ title: "Foo" }, { title: "Bar" }];
background: blue;
}
VerticalLayout {
@@ -29,4 +46,5 @@ export component AppWindow inherits Window {
font-size: 16px;
}
}
}
}

27
ui/sidebar.slint Normal file
View File

@@ -0,0 +1,27 @@
export component ChannelSidebar inherits Rectangle {
in property <bool> open;
in property <[{title: string}]> channel_list;
width: open ? 200px : 0px;
clip: true;
VerticalLayout {
width: 200px;
for channel in channel_list: Text {
text: channel.title;
}
}
}
export component ServerSidebar inherits Rectangle {
in property <bool> open;
in property <[{icon: string}]> server_list;
width: open ? 48px : 0px;
VerticalLayout {
width: 48px;
for server in server_list: Text {
text: server.icon;
}
}
}