// The shapes that cross between Rust and the UI. // // Everything here is already *presentation*: labels are formatted, durations are // strings, covers are decoded images. Nothing in the .slint files formats a number or // picks a word, so the German copy and the duration format live in one place (Rust) // rather than being split across two languages. // // `nav` is each item's position in the single flat selection order that runs songs -> // categories -> albums, so one pair of arrow keys walks the whole page. It is assigned // in Rust, where the three lists are built together. export struct AlbumTile { id: string, title: string, artist: string, // "12 Songs · 45:03 · 🧸" - already assembled, including the figurine marker. meta: string, cover: image, is-book: bool, locked: bool, // This album is the one playing; drawn with the accent ring rather than the // selection ring, and outranked by it when they coincide. current: bool, nav: int, } // The grid is handed to the UI pre-chunked into rows, because a `ListView` virtualizes // its model and a flat list of 343 cards has no rows to skip. This is the direct // counterpart of the web app's `content-visibility: auto` on `.grid > .card`, which // exists for exactly the same measurement: 340 live cards saturated the Pi's renderer. export struct GridRow { tiles: [AlbumTile], } export struct CategoryTile { key: string, // "7 Hörbücher" count-label: string, // Up to four covers in a 2x2, or one filling the tile when the category holds a // single album. Four fields rather than an array: the count is fixed and small, and // this keeps the tile a plain struct. cover1: image, cover2: image, cover3: image, cover4: image, cover-count: int, is-book: bool, nav: int, } export struct CategoryRow { tiles: [CategoryTile], } // One of the three shelves on the root screen. export struct Shelf { label: string, icon: string, tiles: [CategoryTile], empty-label: string, } export struct TrackRow { title: string, subtitle: string, duration: string, cover: image, is-book: bool, current: bool, locked: bool, album-id: string, index: int, nav: int, } // What the player bar and the full-screen view both say. Shared so the two cannot // drift apart on a copy change. export struct NowPlaying { title: string, subtitle: string, // "Song 3 von 8" / "Kapitel 3 von 8" counter: string, cover: image, hero-cover: image, is-book: bool, has-album: bool, // "−4:12", the time left in this track. clock-label: string, // "Noch 38:20 im Album" - empty for a podcast, where it means nothing. remaining-label: string, } // ------------------------------------------------------------- Mein Zimmer -- // One device card on the room page. Lights and shutters share a struct rather than // having one each, because the grid renders them in the order Home Assistant's config // lists them and two models would lose that order. `kind` is what the view branches on. export struct RoomCard { entity-id: string, name: string, // "light" | "shutter" kind: string, on: bool, // --- light --- is-color: bool, // 0..5, matching the five brightness buttons. level: int, tint: color, // Which of the six swatches the light is currently set to, or -1. swatch: int, // --- shutter --- // Percent *closed*: 0 is fully open. Home Assistant reports the opposite; the // inversion happens once, in Rust. closed-percent: float, // "Fährt runter …", or the preset name the position matches. status: string, // "" | "up" | "down" moving: string, supports-position: bool, // Which of the four presets the position matches, or -1. preset: int, } // The room grid, pre-chunked into rows for the same reason the album grid is: the // view lays rows out, and how many fit is a function of the window width, which Rust // is the one that knows. export struct RoomRow { cards: [RoomCard], } export struct SceneTile { entity-id: string, name: string, active: bool, } // One of the six colours a colour-capable light can be set to. export struct Swatch { name: string, tint: color, } // One entry in the vertical tab rail. Built in Rust like every other string on // screen, so the page order, the icons and the German labels live in one place. export struct Tab { id: string, icon: string, label: string, }