mor lint fixes
Some checks failed
/ test (push) Failing after 5m41s

This commit is contained in:
Chris Cochrun 2026-02-15 22:06:55 -06:00
parent 2e8829027a
commit 1c8a0bf450
8 changed files with 92 additions and 132 deletions

View file

@ -369,14 +369,6 @@ impl ServiceTrait for Song {
}
}
const VERSE_KEYWORDS: [&str; 24] = [
"Verse 1", "Verse 2", "Verse 3", "Verse 4", "Verse 5", "Verse 6",
"Verse 7", "Verse 8", "Chorus 1", "Chorus 2", "Chorus 3",
"Chorus 4", "Bridge 1", "Bridge 2", "Bridge 3", "Bridge 4",
"Intro 1", "Intro 2", "Ending 1", "Ending 2", "Other 1",
"Other 2", "Other 3", "Other 4",
];
impl FromRow<'_, SqliteRow> for Song {
fn from_row(row: &SqliteRow) -> sqlx::Result<Self> {
let lyrics: &str = row.try_get("lyrics")?;
@ -518,72 +510,6 @@ impl From<Value> for Song {
}
}
fn lyrics_to_verse(
lyrics: String,
) -> Result<(Vec<VerseName>, HashMap<VerseName, String>)> {
let mut verse_list = Vec::new();
if lyrics.is_empty() {
return Err(miette!("There is no lyrics here"));
}
let raw_lyrics = lyrics.as_str();
let mut lyric_map = HashMap::new();
let mut verse_title = String::new();
let mut lyric = String::new();
for (i, line) in raw_lyrics.split('\n').enumerate() {
if VERSE_KEYWORDS.contains(&line) {
if i != 0 {
lyric_map.insert(verse_title, lyric);
lyric = String::new();
verse_title = line.to_string();
} else {
verse_title = line.to_string();
}
} else {
lyric.push_str(line);
lyric.push('\n');
}
}
lyric_map.insert(verse_title, lyric);
let mut verse_map = HashMap::new();
for (verse_name, lyric) in lyric_map {
let mut verse_elements = verse_name.split_whitespace();
let verse_keyword = verse_elements.next();
let Some(keyword) = verse_keyword else {
return Err(miette!(
"Can't parse a proper verse keyword from lyrics"
));
};
let verse_index = verse_elements.next();
let Some(index) = verse_index else {
return Err(miette!(
"Can't parse a proper verse index from lyrics"
));
};
let index = index.parse::<usize>().into_diagnostic()?;
let verse = match keyword {
"Verse" => VerseName::Verse { number: index },
"Pre-Chorus" => VerseName::PreChorus { number: index },
"Chorus" => VerseName::Chorus { number: index },
"Post-Chorus" => VerseName::PostChorus { number: index },
"Bridge" => VerseName::Bridge { number: index },
"Intro" => VerseName::Intro { number: index },
"Outro" => VerseName::Outro { number: index },
"Instrumental" => {
VerseName::Instrumental { number: index }
}
"Other" => VerseName::Other { number: index },
_ => VerseName::Other { number: 99 },
};
verse_list.push(verse);
let lyric = lyric.trim().to_string();
verse_map.insert(verse, lyric);
}
Ok((verse_list, verse_map))
}
pub fn lisp_to_song(list: Vec<Value>) -> Song {
const DEFAULT_SONG_ID: i32 = 0;
// const DEFAULT_SONG_LOCATION: usize = 0;

View file

@ -1,6 +1,6 @@
use crate::core::model::LibraryKind;
pub mod double_ended_slider;
// pub mod double_ended_slider;
pub mod image_editor;
pub mod library;
pub mod presentation_editor;

View file

@ -50,7 +50,6 @@ pub(crate) struct Presenter {
pub current_slide: Slide,
pub current_item: usize,
pub current_slide_index: usize,
pub absolute_slide_index: usize,
pub total_slides: usize,
pub video: Option<Video>,
pub video_position: f32,
@ -75,6 +74,7 @@ pub(crate) enum Action {
}
#[derive(Clone)]
#[allow(clippy::large_enum_variant)]
pub(crate) enum Message {
NextSlide,
PrevSlide,
@ -168,6 +168,7 @@ enum MenuAction {
ObsStopStream,
ObsStartRecord,
ObsStopRecord,
MidiAction,
}
impl menu::Action for MenuAction {
@ -190,12 +191,13 @@ impl menu::Action for MenuAction {
),
Self::ObsStartRecord => todo!(),
Self::ObsStopRecord => todo!(),
Self::MidiAction => todo!(),
}
}
}
impl Presenter {
fn create_video(url: Url) -> Result<Video> {
fn create_video(url: &Url) -> Result<Video> {
// Based on `iced_video_player::Video::new`,
// but without a text sink so that the built-in subtitle functionality triggers.
use gstreamer as gst;
@ -218,16 +220,35 @@ impl Presenter {
let video_sink: gst::Element =
pipeline.property("video-sink");
let pad = video_sink.pads().first().cloned().unwrap();
let pad = pad.dynamic_cast::<gst::GhostPad>().unwrap();
let pad =
video_sink.pads().first().cloned().expect("first pad");
let pad = pad
.dynamic_cast::<gst::GhostPad>()
.map_err(|_| iced_video_player::Error::Cast)
.into_diagnostic()?;
let bin = pad
.parent_element()
.unwrap()
.ok_or_else(|| {
iced_video_player::Error::AppSink(String::from(
"Should have a parent element here",
))
})
.into_diagnostic()?
.downcast::<gst::Bin>()
.unwrap();
let video_sink = bin.by_name("lumina_video").unwrap();
let video_sink =
video_sink.downcast::<gst_app::AppSink>().unwrap();
.map_err(|_| iced_video_player::Error::Cast)
.into_diagnostic()?;
let video_sink = bin
.by_name("lumina_video")
.ok_or_else(|| {
iced_video_player::Error::AppSink(String::from(
"Can't find element lumina_video",
))
})
.into_diagnostic()?;
let video_sink = video_sink
.downcast::<gst_app::AppSink>()
.map_err(|_| iced_video_player::Error::Cast)
.into_diagnostic()?;
let result =
Video::from_gst_pipeline(pipeline, video_sink, None);
result.into_diagnostic()
@ -239,7 +260,9 @@ impl Presenter {
if let Some(slide) = item.slides.first() {
let path = slide.background().path.clone();
if path.exists() {
let url = Url::from_file_path(path).unwrap();
let url = Url::from_file_path(path).expect(
"There should be a video file here",
);
let result = Video::new(&url);
match result {
Ok(mut v) => {
@ -281,7 +304,6 @@ impl Presenter {
current_slide: slide.unwrap_or(&DEFAULT_SLIDE).clone(),
current_item: 0,
current_slide_index: 0,
absolute_slide_index: 0,
total_slides,
video,
audio,
@ -308,6 +330,7 @@ impl Presenter {
}
}
#[allow(clippy::too_many_lines)]
pub fn update(&mut self, message: Message) -> Action {
match message {
Message::AddObsClient(client) => {
@ -347,17 +370,16 @@ impl Presenter {
self.obs_scenes = Some(scenes);
}
Message::AssignObsScene(scene_index) => {
let slide_id = self.context_menu_id.expect("In this match we should always already have a context menu id");
let Some(scenes) = &self.obs_scenes else {
return Action::None;
};
let new_scene = &scenes[scene_index];
debug!(?scenes, ?new_scene, "updating obs actions");
if let Some(map) = self.slide_action_map.as_mut() {
if let Some(actions) = map.get_mut(
&self.context_menu_id.unwrap_or_default(),
) {
if let Some(actions) = map.get_mut(&slide_id) {
let mut altered_actions = vec![];
actions.iter_mut().for_each(|action| {
for action in actions.iter_mut() {
match action {
slide_actions::Action::Obs {
action: ObsAction::Scene { .. },
@ -371,7 +393,7 @@ impl Presenter {
_ => altered_actions
.push(action.to_owned()),
}
});
}
*actions = altered_actions;
debug!(
"updating the obs scene {:?}",
@ -379,7 +401,7 @@ impl Presenter {
);
} else if map
.insert(
self.context_menu_id.unwrap(),
slide_id,
vec![slide_actions::Action::Obs {
action: ObsAction::Scene {
scene: new_scene.clone(),
@ -401,7 +423,7 @@ impl Presenter {
} else {
let mut map = HashMap::new();
map.insert(
self.context_menu_id.unwrap(),
slide_id,
vec![slide_actions::Action::Obs {
action: ObsAction::Scene {
scene: new_scene.clone(),
@ -412,23 +434,16 @@ impl Presenter {
}
}
Message::AssignSlideAction(action) => {
let slide_id = self.context_menu_id.expect("In this match we should always already have a context menu id");
if let Some(map) = self.slide_action_map.as_mut() {
if let Some(actions) =
map.get_mut(&self.context_menu_id.unwrap())
{
if let Some(actions) = map.get_mut(&slide_id) {
actions.push(action);
} else {
map.insert(
self.context_menu_id.unwrap(),
vec![action],
);
map.insert(slide_id, vec![action]);
}
} else {
let mut map = HashMap::new();
map.insert(
self.context_menu_id.unwrap(),
vec![action],
);
map.insert(slide_id, vec![action]);
self.slide_action_map = Some(map);
}
}
@ -519,7 +534,7 @@ impl Presenter {
{
if let Some(stripped_audio) = new_audio
.to_str()
.unwrap()
.expect("Should be no problem")
.to_string()
.strip_prefix(r"file://")
{
@ -654,7 +669,7 @@ impl Presenter {
Message::None
})
.await
.unwrap()
.expect("Spawning a task shouldn't fail")
},
|x| x,
));
@ -677,13 +692,24 @@ impl Presenter {
}
pub fn view(&self) -> Element<Message> {
slide_view(&self.current_slide, &self.video, false, true)
slide_view(
&self.current_slide,
self.video.as_ref(),
false,
true,
)
}
pub fn view_preview(&self) -> Element<Message> {
slide_view(&self.current_slide, &self.video, false, false)
slide_view(
&self.current_slide,
self.video.as_ref(),
false,
false,
)
}
#[allow(clippy::too_many_lines)]
pub fn preview_bar(&self) -> Element<Message> {
let mut items = vec![];
self.service.iter().enumerate().for_each(
@ -700,7 +726,7 @@ impl Presenter {
let container = slide_view(
slide,
&self.video,
self.video.as_ref(),
true,
false,
);
@ -739,18 +765,18 @@ impl Presenter {
style.shadow = Shadow {
color: Color::BLACK,
offset: {
if is_current_slide {
Vector::new(5.0, 5.0)
} else if hovered {
if is_current_slide
|| hovered
{
Vector::new(5.0, 5.0)
} else {
Vector::new(0.0, 0.0)
}
},
blur_radius: {
if is_current_slide {
10.0
} else if hovered {
if is_current_slide
|| hovered
{
10.0
} else {
0.0
@ -938,8 +964,9 @@ impl Presenter {
BackgroundKind::Video => {
let path = &self.current_slide.background().path;
if path.exists() {
let url = Url::from_file_path(path).unwrap();
let result = Self::create_video(url);
let url = Url::from_file_path(path)
.expect("There should be a video file here");
let result = Self::create_video(&url);
match result {
Ok(mut v) => {
v.set_looping(
@ -1028,9 +1055,13 @@ async fn obs_scene_switch(client: Arc<Client>, scene: Scene) {
#[allow(clippy::unused_async)]
async fn start_audio(sink: Arc<Sink>, audio: PathBuf) {
debug!(?audio);
let file = BufReader::new(File::open(audio).unwrap());
let file = BufReader::new(
File::open(audio)
.expect("There should be an audio file here"),
);
debug!(?file);
let source = Decoder::new(file).unwrap();
let source = Decoder::new(file)
.expect("There should be an audio decoder here");
sink.append(source);
let empty = sink.empty();
let paused = sink.is_paused();
@ -1050,7 +1081,7 @@ fn scale_font(font_size: f32, width: f32) -> f32 {
pub(crate) fn slide_view<'a>(
slide: &'a Slide,
video: &'a Option<Video>,
video: Option<&'a Video>,
delegate: bool,
hide_mouse: bool,
) -> Element<'a, Message> {

View file

@ -25,7 +25,7 @@ pub const fn service<Message: Clone + 'static>(
}
pub struct Service<'a, Message> {
service: &'a Vec<ServiceItem>,
items: &'a Vec<ServiceItem>,
on_start: Option<Message>,
on_cancelled: Option<Message>,
on_finish: Option<Message>,
@ -36,9 +36,9 @@ pub struct Service<'a, Message> {
impl<'a, Message: Clone + 'static> Service<'a, Message> {
#[must_use]
pub const fn new(service: &'a Vec<ServiceItem>) -> Self {
pub const fn new(service_items: &'a Vec<ServiceItem>) -> Self {
Self {
service,
items: service_items,
drag_threshold: 8.0,
on_start: None,
on_cancelled: None,
@ -93,11 +93,13 @@ impl<'a, Message: Clone + 'static> Service<'a, Message> {
// );
// }
#[must_use]
pub fn on_start(mut self, on_start: Option<Message>) -> Self {
self.on_start = on_start;
self
}
#[must_use]
pub fn on_cancel(
mut self,
on_cancelled: Option<Message>,
@ -106,6 +108,7 @@ impl<'a, Message: Clone + 'static> Service<'a, Message> {
self
}
#[must_use]
pub fn on_finish(mut self, on_finish: Option<Message>) -> Self {
self.on_finish = on_finish;
self
@ -289,7 +292,7 @@ impl<Message: Clone + 'static>
_viewport: &Rectangle,
) {
// let state = tree.state.downcast_mut::<State>();
for _item in self.service {}
for _item in self.items {}
}
// fn overlay<'b>(

View file

@ -74,6 +74,7 @@ impl SlideEditor {
/// Ensure to use the `cosmic::Theme and cosmic::Renderer` here
/// or else it will not compile
#[allow(clippy::extra_unused_lifetimes)]
impl<'a> Program<SlideWidget, cosmic::Theme, cosmic::Renderer>
for EditorProgram
{

View file

@ -33,8 +33,7 @@ use cosmic::{
dropdown,
grid::{self},
horizontal_space, icon, mouse_area, popover, progress_bar,
scrollable, spin_button, text, text_editor, text_input,
tooltip,
scrollable, text, text_editor, text_input, tooltip,
},
};
use derive_more::Debug;
@ -107,6 +106,7 @@ pub struct SongEditor {
importing: bool,
}
#[allow(clippy::large_enum_variant)]
pub enum Action {
Task(Task<Message>),
UpdateSong(Song),
@ -189,7 +189,7 @@ impl Display for Face {
};
// need to figure out how to parse this out and then back into something
f.write_str(&format!("{name}{weight}{style}"))
write!(f, "{name}{weight}{style}")
}
}
@ -204,7 +204,6 @@ impl SongEditor {
})
.map(|f| Face(f.clone()))
.collect();
let stroke_sizes = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let font_sizes = vec![
"5".to_string(),
"6".to_string(),
@ -928,9 +927,9 @@ impl SongEditor {
slide_view(
slide,
if index == 0 {
&self.video
self.video.as_ref()
} else {
&None
None
},
false,
false,

View file

@ -306,7 +306,7 @@ impl TextSvg {
return self;
};
path.push(PathBuf::from("lumina"));
path.push(PathBuf::from("temp"));
path.push(PathBuf::from("text_svg_cache"));
let _ = fs::create_dir_all(&path);
let mut final_svg = String::with_capacity(1024);

View file

@ -1,7 +1,7 @@
use cosmic::{
Element, Task,
cosmic_theme::palette::WithAlpha,
iced::{Background, Border, Point},
iced::{Background, Border},
iced_widget::{column, row},
theme,
widget::{