-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix code warnings and clean up the code base (#156)
* rename some structs in the cache_event module so that the warning about item starting with a partial name of the parent module is eliminated * fix the too many lines warning by explicitly allowing it for the macro generated fun ction * fix first wave of warnings * formatting * remove unreferenced macro in tests module since the tests in object.rs were removed in previous commits because they depended on functions marked as unused, this macro remained entirely unused, so it got removed Because most of the functions in those modules are marked unused with the recent refactor, the tests testing them are equally invalid now, so better to make new, more relevant tests later, upon existing code * fix wave 2 of warnings * fix final wave of warnings * remove the object module entirely, as none of its functions are needed * remove the modes and screenreader events machinery, as it's not being used anyway and probably a better way with tower can be found * formatting fixes, blame my code editor for modifying files in which I wasn't directly working * add a way for odilia to speak the roles of accessible controls as well as controls with more complicate labeling For the labeling, we first check if the text is empty. If so, we check both name and description. If that's empty too, we look through the relationship set of objects, to see if there any labeled by relationships, and if so, extract the text from those labels instead Some useless commented code was also removed, as well as other general cleanup
- Loading branch information
1 parent
6c50f0c
commit 722ceb4
Showing
8 changed files
with
59 additions
and
931 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,209 +1,2 @@ | ||
mod cache; | ||
mod document; | ||
mod object; | ||
|
||
use std::sync::Arc; | ||
|
||
use futures::stream::StreamExt; | ||
use tokio::sync::mpsc::{Receiver, Sender}; | ||
use tokio_util::sync::CancellationToken; | ||
|
||
use crate::state::ScreenReaderState; | ||
use atspi_common::events::Event; | ||
use atspi_common::{Role, ScrollType}; | ||
use odilia_cache::AccessibleExt; | ||
use odilia_cache::Convertable; | ||
use odilia_common::{ | ||
events::{Direction, ScreenReaderEvent}, | ||
result::OdiliaResult, | ||
}; | ||
use ssip_client_async::Priority; | ||
|
||
#[tracing::instrument(level = "debug", skip_all, ret, err)] | ||
pub async fn structural_navigation( | ||
state: &ScreenReaderState, | ||
dir: Direction, | ||
role: Role, | ||
) -> OdiliaResult<bool> { | ||
tracing::debug!("Structural nav call begins!"); | ||
let curr = match state.history_item(0) { | ||
Some(acc) => acc.into_accessible(state.atspi.connection()).await?, | ||
None => return Ok(false), | ||
}; | ||
if let Some(next) = curr.get_next(role, dir == Direction::Backward).await? { | ||
let comp = next.to_component().await?; | ||
let texti = next.to_text().await?; | ||
let curr_prim = curr.try_into()?; | ||
let _: bool = comp.grab_focus().await?; | ||
comp.scroll_to(ScrollType::TopLeft).await?; | ||
state.update_accessible(curr_prim); | ||
let _: bool = texti.set_caret_offset(0).await?; | ||
let role = next.get_role().await?; | ||
let len = texti.character_count().await?; | ||
let text = texti.get_text(0, len).await?; | ||
// saying awaits until it is done talking; you may want to spawn a task | ||
state.say(Priority::Text, format!("{text}, {role}")).await; | ||
Ok(true) | ||
} else { | ||
state.say(Priority::Text, format!("No more {role}s")).await; | ||
Ok(true) | ||
} | ||
} | ||
|
||
#[tracing::instrument(level = "debug", skip(state), ret, err)] | ||
pub async fn sr_event( | ||
state: Arc<ScreenReaderState>, | ||
mut sr_events: Receiver<ScreenReaderEvent>, | ||
shutdown: CancellationToken, | ||
) -> eyre::Result<()> { | ||
loop { | ||
tokio::select! { | ||
sr_event = sr_events.recv() => { | ||
tracing::debug!("SR Event received"); | ||
match sr_event { | ||
Some(ScreenReaderEvent::StructuralNavigation(dir, role)) => { | ||
if let Err(e) = structural_navigation(&state, dir, role).await { | ||
tracing::debug!(error = %e, "There was an error with the structural navigation call."); | ||
} else { | ||
tracing::debug!("Structural navigation successful!"); | ||
} | ||
}, | ||
Some(ScreenReaderEvent::StopSpeech) => { | ||
tracing::debug!("Stopping speech!"); | ||
state.stop_speech().await; | ||
}, | ||
Some(ScreenReaderEvent::ChangeMode(new_sr_mode)) => { | ||
tracing::debug!("Changing mode to {:?}", new_sr_mode); | ||
if let Ok(mut sr_mode) = state.mode.lock() { | ||
*sr_mode = new_sr_mode; | ||
} | ||
} | ||
_ => { continue; } | ||
}; | ||
continue; | ||
} | ||
() = shutdown.cancelled() => { | ||
tracing::debug!("sr_event cancelled"); | ||
break; | ||
} | ||
} | ||
} | ||
Ok(()) | ||
} | ||
|
||
#[tracing::instrument(level = "debug", skip_all)] | ||
pub async fn receive( | ||
state: Arc<ScreenReaderState>, | ||
tx: Sender<Event>, | ||
shutdown: CancellationToken, | ||
) { | ||
let events = state.atspi.event_stream(); | ||
tokio::pin!(events); | ||
loop { | ||
tokio::select! { | ||
event = events.next() => { | ||
if let Some(Ok(good_event)) = event { | ||
if let Err(e) = tx.send(good_event).await { | ||
tracing::error!(error = %e, "Error sending atspi event"); | ||
} | ||
} else { | ||
tracing::debug!("Event is either None or an Error variant."); | ||
} | ||
continue; | ||
} | ||
() = shutdown.cancelled() => { | ||
tracing::debug!("receive function is done"); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[tracing::instrument(level = "debug", skip_all)] | ||
pub async fn process( | ||
state: Arc<ScreenReaderState>, | ||
mut rx: Receiver<Event>, | ||
shutdown: CancellationToken, | ||
) { | ||
loop { | ||
tokio::select! { | ||
event = rx.recv() => { | ||
match event { | ||
Some(good_event) => { | ||
let state_arc = Arc::clone(&state); | ||
tokio::task::spawn( | ||
dispatch_wrapper(state_arc, good_event) | ||
); | ||
}, | ||
None => { | ||
tracing::debug!("Event was none."); | ||
} | ||
}; | ||
continue; | ||
} | ||
() = shutdown.cancelled() => { | ||
tracing::debug!("process function is done"); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[tracing::instrument(level = "debug", skip(state))] | ||
async fn dispatch_wrapper(state: Arc<ScreenReaderState>, good_event: Event) { | ||
if let Err(e) = dispatch(&state, good_event).await { | ||
tracing::error!(error = %e, "Could not handle event"); | ||
} else { | ||
tracing::debug!("Event handled without error"); | ||
} | ||
} | ||
|
||
#[tracing::instrument(level = "debug", skip(state), ret, err)] | ||
async fn dispatch(state: &ScreenReaderState, event: Event) -> eyre::Result<()> { | ||
// Dispatch based on interface | ||
match &event { | ||
Event::Object(object_event) => { | ||
object::dispatch(state, object_event).await?; | ||
} | ||
Event::Document(document_event) => { | ||
document::dispatch(state, document_event).await?; | ||
} | ||
Event::Cache(cache_event) => cache::dispatch(state, cache_event).await?, | ||
other_event => { | ||
tracing::debug!( | ||
"Ignoring event with unknown interface: {:#?}", | ||
other_event | ||
); | ||
} | ||
} | ||
state.event_history_update(event); | ||
Ok(()) | ||
} | ||
|
||
#[cfg(test)] | ||
pub mod dispatch_tests { | ||
use crate::ScreenReaderState; | ||
use eyre::Context; | ||
use odilia_common::settings::ApplicationConfig; | ||
use tokio::sync::mpsc::channel; | ||
|
||
#[tokio::test] | ||
async fn test_full_cache() -> eyre::Result<()> { | ||
let state = generate_state().await?; | ||
assert_eq!(state.cache.by_id.len(), 14_738); | ||
Ok(()) | ||
} | ||
|
||
pub async fn generate_state() -> eyre::Result<ScreenReaderState> { | ||
let (send, _recv) = channel(32); | ||
let cache = serde_json::from_str(include_str!("wcag_cache_items.json")) | ||
.context("unable to load cache data from json file")?; | ||
let state = ScreenReaderState::new(send, ApplicationConfig::default()) | ||
.await | ||
.context("unable to realise screenreader state")?; | ||
state.cache | ||
.add_all(cache) | ||
.context("unable to add cache to the system")?; | ||
Ok(state) | ||
} | ||
} |
Oops, something went wrong.