// #![cfg_attr(not(feature = "simulator"), no_main)] use alloc::{boxed::Box, ffi::CString}; use log::{info, warn}; use slint::SharedString; use spectre_api_sys::{SpectreAlgorithm, SpectreCounter, SpectreKeyPurpose, SpectreUserKey}; #[cfg(feature = "limit-fps")] use crate::FRAME_DURATION_MIN; use crate::{SIGNAL_LCD_SUBMIT, SIGNAL_UI_RENDER, ui::backend::SlintBackend}; pub mod backend; pub mod window_adapter; slint::include_modules!(); #[embassy_executor::task] pub async fn run_renderer_task(backend: SlintBackend) { slint::platform::set_platform(Box::new(backend)).expect("backend already initialized"); let main = AppWindow::new().unwrap(); let mut buffer = CString::default(); main.on_accepted(|string| { warn!("Accepted: {string}"); let Ok(c_string) = CString::new(&*string) else { warn!("String cannot be converted to a C string: {string:?}"); return; }; unsafe { let user_key = &*spectre_api_sys::spectre_user_key( c"test".as_ptr(), c_string.as_ptr(), SpectreAlgorithm::Current, ); warn!("{user_key:?}"); let site_key = &*spectre_api_sys::spectre_site_key( user_key as *const SpectreUserKey, c"example.org".as_ptr(), SpectreCounter::Initial, SpectreKeyPurpose::Authentication, c"".as_ptr(), ); warn!("{site_key:?}"); // TODO: Free memory } }); // Instead of having a `loop` in the non-async `SlintBackend::run_event_loop`, we achieve // async by having only one iteration of the loop run, and `await`ing here. // The following block is analogous to `main.run()`. { main.show().unwrap(); loop { slint::run_event_loop().unwrap(); SIGNAL_LCD_SUBMIT.signal(()); #[cfg(feature = "limit-fps")] embassy_time::Timer::after(FRAME_DURATION_MIN).await; SIGNAL_UI_RENDER.wait().await; } #[expect(unreachable_code)] main.hide().unwrap(); } }