KeyCode::Enter => {
match self.player.focused_widget {
Focus::Tracklist => {
match self.player.mode {
Mode::Default => {
if let Some((_, selected_list)) =
&self.player.tracklist.selected_playlist
{
self.player.tracklist.base = selected_list.clone();
} else {
self.player.tracklist.base = self.tracks.clone();
};
let index = match self.shuffle {
Shuffle::Random => {
self.player.tracklist.list =
self.player.tracklist.base.clone();
let index = (self.player.tracklist.cursor
+ self.player.tracklist.y_offset)
as usize;
self.player.tracklist.list.swap(index, 0);
self.player.tracklist.list[1..]
.shuffle(&mut rand::rng());
0
}
_ => {
self.player.tracklist.list =
self.player.tracklist.base.clone();
let index = (self.player.tracklist.cursor
+ self.player.tracklist.y_offset)
as usize;
index
}
};
self.player.set_auto_queue(index);
let track = self.player.pop_auto_queue().unwrap();
self.play(track);
}
Mode::Select => {}
}
}
Focus::Playlist => match self.player.mode {
Mode::Default => {
let playlist = self.player.playlist.get_under_cursor();
let db_tracks =
DbTrack::get_by_playlist_uuid(&self.db_conn, playlist.uuid);
let tracks = Track::from_db_tracks(&self.tracks, db_tracks);
self.player.tracklist.selected_playlist =
Some((playlist, tracks));
self.player.switch_window();
self.player.tracklist.y_offset = 0;
self.player.tracklist.cursor = 0;
}
Mode::Select => {
let playlist = self.player.playlist.get_under_cursor();
let db_tracks =
DbTrack::get_by_playlist_uuid(&self.db_conn, playlist.uuid);
let tracks = Track::from_db_tracks(&self.tracks, db_tracks);
let selected_track =
self.player.playlist.selected_track.take().unwrap();
if tracks
.iter()
.find(|t| t.uuid == selected_track.uuid)
.is_some()
{
self.player.mode = Mode::Default;
self.player.switch_window();
return;
}
selected_track
.insert_into_playlist(playlist.uuid, &self.db_conn);
self.player.mode = Mode::Default;
self.player.switch_window();
}
},
}
}
I have parent widget App
that handles all inputs and resolves anything related to other threads and database. It has main component Player
. Player
has at least 4 states for now. 2 are focused widgets and 2 are modes (Select or Default).
All of them need to do something different when enter
is pressed.
Focus::Tracklist
with Mode::Default
pops new audio to play it on a different thread. The rest doesn’t return anything. But they can fail, and in future i want to handle those too.
I’ve tried to make dispatch
function, but it looks like i have to use Message
enum. And now i don’t need it anywhere but Enter
handling. So it would be overkill probably. I might be wrong here.
I’ve considered how iced
approached it.
The downsides are:
- Majority of events will return
Message::None
- Event loop will have to read event, call the function and always match the message, returned from function.
For now i’m handling it directly in App
. It wouldn’t be a problem, but there are multiple places where i need to do something that relies on state of Player
, so in every place like that i need to do nested matches. And i only started to implement functionality. In future there will be even more places where i need to do the same. But amount of places where Message::None
is returned will increase as well.
My questions are:
- Does
Message
approach gives more upsides than downsides? - How else can i handle it if i don’t want to use
Message
? - Maybe i should give up on centralized event reading? But in that case i don’t know other patterns to make decentralized system.