cranpose_services/
accessibility_state.rs1use std::cell::{Cell, RefCell};
6
7use cranpose_core::{CompositionLocal, CompositionLocalProvider, compositionLocalOf};
8use cranpose_macros::composable;
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
12pub struct AccessibilityState {
13 pub screen_reader_on: bool,
17}
18
19thread_local! {
20 static PLATFORM_ACCESSIBILITY_STATE: Cell<AccessibilityState> =
21 const { Cell::new(AccessibilityState { screen_reader_on: false }) };
22}
23
24pub fn set_platform_accessibility_state(state: AccessibilityState) -> bool {
28 PLATFORM_ACCESSIBILITY_STATE.with(|cell| {
29 let changed = cell.get() != state;
30 cell.set(state);
31 changed
32 })
33}
34
35pub fn platform_accessibility_state() -> AccessibilityState {
37 PLATFORM_ACCESSIBILITY_STATE.with(Cell::get)
38}
39
40pub fn local_accessibility_state() -> CompositionLocal<AccessibilityState> {
43 thread_local! {
44 static LOCAL: RefCell<Option<CompositionLocal<AccessibilityState>>> =
45 const { RefCell::new(None) };
46 }
47
48 LOCAL.with(|cell| {
49 let mut local = cell.borrow_mut();
50 local
51 .get_or_insert_with(|| compositionLocalOf(platform_accessibility_state))
52 .clone()
53 })
54}
55
56#[composable]
59pub fn ProvideAccessibilityState(state: AccessibilityState, content: impl FnOnce()) {
60 let local = local_accessibility_state();
61 CompositionLocalProvider(vec![local.provides(state)], move || {
62 content();
63 });
64}
65
66#[cfg(test)]
67#[path = "tests/accessibility_state_tests.rs"]
68mod tests;