this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

chose iced, documented decision and basics

+327 -19
+19 -17
AGENTS.md
··· 27 27 28 28 key decisions 29 29 ------------- 30 - 2025-10-25: chose dioxus desktop (standalone) 30 + 2025-10-25: chose iced 31 31 why: 32 - - native rendering (not webview/DOM) 33 - - react-like syntax (familiar) 34 - - no tauri IPC boundary issues 35 - - handles large datasets well 36 - - windows support + accessibility 32 + - TRUE native rendering (no DOM/webview) 33 + - elm architecture (clean patterns) 34 + - handles 60k items natively 35 + - system76 backing (cosmic desktop) 36 + - actual GPU performance 37 37 38 38 rejected: 39 - - tauri: IPC boundary loses type safety 40 - - egui: immediate mode, less familiar 41 - - iced: accessibility gaps 42 - - yew: older, heavier 39 + - tauri: IPC boundary loses type safety, still DOM 40 + - dioxus: discovered it uses webview/DOM anyway 41 + - egui: immediate mode, friend suggested iced instead 42 + - yew: older, heavier, still web tech 43 + 44 + tradeoffs accepted: 45 + - accessibility gaps (screen reader/IME) 46 + - we're okay with this for now 43 47 44 48 45 49 architecture notes 46 50 ------------------ 47 51 tech stack: 48 - - dioxus desktop (native rendering) 52 + - iced (native GPU rendering) 49 53 - rust for data handling 50 54 - radio4000 API for data source 51 55 52 - getting started: 53 - cargo install dioxus-cli --locked 54 - 55 - optional (if we need tauri later): 56 - cargo install tauri-cli --version '^2.0.0' --locked 56 + structure: 57 + /r4 → dioxus prototype (abandoned) 58 + TBD → new iced project 57 59 58 60 59 61 .---. ··· 77 79 - changelog format → ~/Notes/changelogs.md 78 80 79 81 80 - last updated: 2025-10-25 (chose dioxus, defined project goal) 82 + last updated: 2025-10-25 (chose iced after exploring options)
+232
docs/iced.txt
··· 1 + iced reference 2 + ============== 3 + 4 + source: https://docs.iced.rs/iced/ 5 + 6 + 7 + the elm architecture 8 + -------------------- 9 + 10 + iced follows the elm architecture with four core parts: 11 + 12 + state → the data (struct with fields) 13 + messages → interactions (enum variants) 14 + update → how messages change state (fn) 15 + view → how state dictates widgets (fn) 16 + 17 + flow: 18 + widgets produce messages 19 + messages trigger update 20 + update changes state 21 + state dictates new view 22 + repeat... 23 + 24 + 25 + basic structure 26 + --------------- 27 + 28 + pub fn main() -> iced::Result { 29 + iced::run(update, view) 30 + } 31 + 32 + fn update(state: &mut State, message: Message) { 33 + match message { 34 + Message::Increment => state.value += 1, 35 + } 36 + } 37 + 38 + fn view(state: &State) -> Element<'_, Message> { 39 + button(text(state.value)) 40 + .on_press(Message::Increment) 41 + .into() 42 + } 43 + 44 + #[derive(Debug, Clone)] 45 + enum Message { 46 + Increment, 47 + } 48 + 49 + 50 + widgets 51 + ------- 52 + 53 + widgets are VALUES not side effects 54 + created with helper functions from iced::widget 55 + 56 + button("+") → button widget 57 + text("hello") → text widget 58 + column![a, b, c] → vertical layout 59 + row![a, b, c] → horizontal layout 60 + container(widget) → positioning/alignment 61 + 62 + configured with builder pattern: 63 + button("+") 64 + .on_press(Message::Inc) 65 + .style(button::primary) 66 + .width(Fill) 67 + 68 + 69 + layout 70 + ------ 71 + 72 + no unified layout system 73 + each widget has its own strategy 74 + 75 + common patterns: 76 + - column for vertical stacking 77 + - row for horizontal stacking 78 + - container for positioning/centering 79 + - spacing() for gaps between children 80 + 81 + container( 82 + column![ 83 + "Top", 84 + row!["Left", "Right"].spacing(10), 85 + "Bottom" 86 + ].spacing(10) 87 + ) 88 + .padding(10) 89 + .center_x(Fill) 90 + .center_y(Fill) 91 + 92 + 93 + sizing 94 + ------ 95 + 96 + Length enum controls widget dimensions: 97 + 98 + Fill → take all available space 99 + Shrink → use intrinsic size (default) 100 + Pixels(n) → fixed size 101 + 102 + container("text") 103 + .height(300) 104 + .width(Fill) 105 + 106 + 107 + styling 108 + ------- 109 + 110 + each widget has .style() method 111 + takes closure: (theme, status) -> style 112 + 113 + button("Click") 114 + .style(|theme: &Theme, status| { 115 + match status { 116 + button::Status::Active => { 117 + button::Style::default() 118 + .with_background(theme.palette().primary) 119 + } 120 + _ => button::primary(theme, status) 121 + } 122 + }) 123 + 124 + convenience functions: 125 + - container::rounded_box 126 + - button::primary 127 + - text::danger 128 + 129 + 130 + theming 131 + ------- 132 + 133 + use application builder for custom theme: 134 + 135 + iced::application(new, update, view) 136 + .theme(theme) 137 + .run() 138 + 139 + fn theme(state: &State) -> Theme { 140 + Theme::TokyoNight 141 + } 142 + 143 + built-in themes: 144 + - Theme::Dark 145 + - Theme::Light 146 + - Theme::TokyoNight 147 + - etc 148 + 149 + 150 + tasks (async work) 151 + ------------------ 152 + 153 + update can return Task<Message> 154 + used for async operations 155 + 156 + fn update(state: &mut State, msg: Message) -> Task<Message> { 157 + match msg { 158 + Message::Fetch => { 159 + Task::perform(fetch_data(), Message::Fetched) 160 + } 161 + Message::Fetched(data) => { 162 + state.data = Some(data); 163 + Task::none() 164 + } 165 + } 166 + } 167 + 168 + tasks can: 169 + - run futures/streams 170 + - interact with runtime (window, focus, etc) 171 + - be mapped, chained, batched, canceled 172 + 173 + 174 + subscriptions (passive data) 175 + ----------------------------- 176 + 177 + subscribe to external events: 178 + - time ticks 179 + - window resize 180 + - keyboard events 181 + 182 + fn subscription(state: &State) -> Subscription<Message> { 183 + window::resize_events() 184 + .map(|(_, size)| Message::Resized(size)) 185 + } 186 + 187 + subscriptions are declarative 188 + only what's returned is active (like view) 189 + 190 + 191 + scaling apps 192 + ------------ 193 + 194 + update/view/message compose nicely 195 + common pattern: split into screens 196 + 197 + enum Screen { 198 + Contacts(Contacts), 199 + Chat(Chat), 200 + } 201 + 202 + enum Message { 203 + Contacts(contacts::Message), 204 + Chat(chat::Message), 205 + } 206 + 207 + each screen has own update/view 208 + parent coordinates via Action enum 209 + use .map() to compose messages 210 + 211 + screen.view().map(Message::Contacts) 212 + 213 + 214 + key principles 215 + -------------- 216 + 217 + - widgets are values, no side effects 218 + - state is application-specific 219 + - type system prevents invalid states 220 + - messages are pure data (derive Debug, Clone) 221 + - view is pure function of state 222 + - leverages rust: ownership, traits, enums, etc 223 + 224 + 225 + important types 226 + --------------- 227 + 228 + Element<'a, Message> → generic widget 229 + Task<Message> → async work 230 + Subscription<Message> → passive events 231 + Length → Fill, Shrink, Pixels(n) 232 + Theme → appearance
+74
docs/workflow.txt
··· 1 + workflow 2 + ======== 3 + 4 + principles 5 + ---------- 6 + - docs are for agents to rebuild context quickly 7 + - AGENTS.md is the entry point for new sessions 8 + - todo.txt tracks current work 9 + - CHANGELOG.md tracks what's done 10 + - jj for version control (see ~/Notes/jj.md) 11 + 12 + 13 + onboarding new context 14 + ---------------------- 15 + when starting fresh: 16 + 1. read AGENTS.md (or CLAUDE.md symlink) 17 + 2. read todo.txt to see current tasks 18 + 3. check relevant docs/ files as needed 19 + 4. check CHANGELOG.md for recent history 20 + 21 + 22 + docs structure 23 + -------------- 24 + AGENTS.md → main context file for AI agents 25 + CLAUDE.md → symlink to AGENTS.md 26 + README.md → project overview 27 + todo.txt → current work, backlog 28 + CHANGELOG.md → completed work history 29 + 30 + docs/ 31 + README.md → docs folder overview 32 + iced.txt → iced framework reference 33 + workflow.txt → this file 34 + 35 + 36 + working with jj 37 + --------------- 38 + use freely: 39 + jj describe -m "message" → describe current change 40 + jj new → start new change 41 + 42 + see ~/Notes/jj.md for full reference 43 + 44 + 45 + completing tasks 46 + ---------------- 47 + 1. do the work 48 + 2. update CHANGELOG.md with what changed 49 + 3. check off in todo.txt or move to backlog 50 + 4. jj describe + jj new 51 + 5. update AGENTS.md if decisions made 52 + 53 + 54 + context files to read first 55 + --------------------------- 56 + always start with: 57 + - AGENTS.md (decisions, status, references) 58 + - todo.txt (what's next) 59 + 60 + read as needed: 61 + - docs/iced.txt (framework reference) 62 + - docs/workflow.txt (this file) 63 + - CHANGELOG.md (history) 64 + 65 + 66 + keeping context fresh 67 + --------------------- 68 + update AGENTS.md when: 69 + - making architecture decisions 70 + - learning something important 71 + - changing approach 72 + 73 + keep it concise, use our ascii style 74 + future you (or other agent) will thank you
+2 -2
todo.txt
··· 3 3 4 4 next 5 5 ---- 6 - [ ] install dioxus-cli 7 - [ ] create initial dioxus desktop project 6 + [ ] create iced project 7 + [ ] hello world in iced 8 8 [ ] fetch radio4000 data structure 9 9 10 10