Ideally episodes would be marked as played only when they have
passed a cerain point in their duration, but till thats ready
we should keep marking them.
Previously each time we wanted to inspect the `Progress` struct we
were blocking which was problematic since the downloader also wants
to block to update it.
Now we use try_lock() and if a lock can't be aquired we requeue another
callback. That way we can also be way more aggressive about the interval
in whihc it the callbacks will run.
If an episode is being downloaded we setup a callback that will
supervise the widget and update it's state once the download action is
completed and the episode rowid is removed from `manager::ACTIVEDOWNLOADS`.
The size might be provided by the rss feed but not alwasy. Additionally it might be
missleading so when a download starts we replace the label with the
HTTP ContentLength header.
State machines were a fun experiement but a nightmare to deal with
after the fact. This is the first steps for a refactor in a tradition
style with the goal to ultimatly making it easy to and port to relm.
This code is ugly and terrible but it works™. Previsously when a download
would finish it would refresh all the views. Now the if the widget get's
into the Donwloading state, it will setup a callback that will check
periodicly if it's still downloading and update the widget state when
the episode stops downloading.
Since gtk Widgets are not Send, and the callbacks all run in the gtk
main loop, it *should* not be possible that 2 things try to access the
same widget at the same time.
When iteration of data is finished, None will be returned and
the or_else() block will be executed. Now a callback can be
passed that will be executd when the iteration/loading finishes.
Previously we would refresh all the views when download/cancel
button was clicked. This was done mainly to avoid zombie widget bugs
that would arise from shared state.
Now we still refresh all the background views but not the visible one.
Instead the widget has the reponsibility of recalculating it's state.
make the data: Vec<T> mutable, then reverse the vector
so it can be used as a stack, and then use the ::pop()
method to retrieve the item.
This also avoid the constrain for Clone on T.
The state machines are not send and the code is sequnecial.
We only need `&mut machine` refference to pass to `take_mut::take`
to change the state of the machine. In 2/3 cases we can even use
`.get_mut()` method and even avoid the dynamic borrow checks at
runtime. For the `TitleMachine` The only thing that will hold
a refference to it after initialization will be the play_button
callback. So it's justifiable to use `RefCell` insetead of a `Mutex`.
`DateMachine` and `DurationMachine` are only mutated during initialization
and thus do not need shared ownership.
`TitleMachine` is only mutated during initialization and after that only
the callback will keep holding a referrence to it. The `EpisodeWidget`s
get dropped after initialization. So it's justifiable to use `Rc<Mutex<T>>`
instead of `Arc`.