diff --git a/Cargo.lock b/Cargo.lock index bc9dfff..958e746 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml index 3c80918..da69484 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/NOTES.md b/NOTES.md index 35d15a4..f04ac67 100644 --- a/NOTES.md +++ b/NOTES.md @@ -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. diff --git a/src/api.rs b/src/api.rs new file mode 100644 index 0000000..f931ebc --- /dev/null +++ b/src/api.rs @@ -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, + // media server + january: Option, + // + voso: Option, + // voip server + livekit: Option, +} + +#[derive(serde::Deserialize, Debug)] +struct ServerFeatureEndpoint { + enabled: bool, + url: Option, + ws: Option, +} diff --git a/src/main.rs b/src/main.rs index c251e1f..776f5b2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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> { + 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({ diff --git a/ui/app-window.slint b/ui/app-window.slint index 6629e27..8b4cf01 100644 --- a/ui/app-window.slint +++ b/ui/app-window.slint @@ -1,32 +1,50 @@ 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"; - VerticalLayout { + property sidebar-open: true; - ChatView { - messages: [ - { text: "hello", sender: "Bob", time: "10:00" }, - { text: "hey!", sender: "Joe", time: "10:01" }, - { text: "i like cats c:", sender: "Bob", time: "10:03" }, - { text: "me too c:", sender: "Joe", time: "10:08" }, - { - text: "meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow ", - sender: "Joe", - time: "10:08" - }, - { - text: "meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow ", - sender: "Bob", - time: "10:12" - }, - ]; + HorizontalLayout { + ServerSidebar { + open: root.width > 600px; + server_list: [{ icon: "😳" }, { icon: "😍" }]; + background: yellow; } - TextEdit { - height: 64px; - font-size: 16px; + ChannelSidebar { + open: root.width > 600px ? sidebar-open : false; + channel_list: [{ title: "Foo" }, { title: "Bar" }]; + background: blue; + } + + VerticalLayout { + + ChatView { + messages: [ + { text: "hello", sender: "Bob", time: "10:00" }, + { text: "hey!", sender: "Joe", time: "10:01" }, + { text: "i like cats c:", sender: "Bob", time: "10:03" }, + { text: "me too c:", sender: "Joe", time: "10:08" }, + { + text: "meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow ", + sender: "Joe", + time: "10:08" + }, + { + text: "meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow ", + sender: "Bob", + time: "10:12" + }, + ]; + } + + TextEdit { + height: 64px; + font-size: 16px; + } } } } diff --git a/ui/sidebar.slint b/ui/sidebar.slint new file mode 100644 index 0000000..aa63f01 --- /dev/null +++ b/ui/sidebar.slint @@ -0,0 +1,27 @@ +export component ChannelSidebar inherits Rectangle { + in property 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 open; + in property <[{icon: string}]> server_list; + + width: open ? 48px : 0px; + VerticalLayout { + width: 48px; + for server in server_list: Text { + text: server.icon; + } + } +}