EpisodeWidget: Wire the download_checker callback again.
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`.
This commit is contained in:
parent
a090c11f4a
commit
04e7f4f8a7
@ -38,7 +38,6 @@ extern crate regex;
|
|||||||
extern crate reqwest;
|
extern crate reqwest;
|
||||||
extern crate send_cell;
|
extern crate send_cell;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate take_mut;
|
|
||||||
extern crate url;
|
extern crate url;
|
||||||
|
|
||||||
use log::Level;
|
use log::Level;
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
#![allow(warnings)]
|
|
||||||
|
|
||||||
use glib;
|
use glib;
|
||||||
use gtk;
|
use gtk;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
@ -10,7 +8,6 @@ use crossbeam_channel::Sender;
|
|||||||
use failure::Error;
|
use failure::Error;
|
||||||
use humansize::{file_size_opts as size_opts, FileSize};
|
use humansize::{file_size_opts as size_opts, FileSize};
|
||||||
use open;
|
use open;
|
||||||
use take_mut;
|
|
||||||
|
|
||||||
use hammond_data::dbqueries;
|
use hammond_data::dbqueries;
|
||||||
use hammond_data::utils::get_download_folder;
|
use hammond_data::utils::get_download_folder;
|
||||||
@ -18,14 +15,29 @@ use hammond_data::EpisodeWidgetQuery;
|
|||||||
|
|
||||||
use app::Action;
|
use app::Action;
|
||||||
use manager;
|
use manager;
|
||||||
use widgets::episode_states::*;
|
|
||||||
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::ops::DerefMut;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref SIZE_OPTS: Arc<size_opts::FileSizeOpts> = {
|
||||||
|
// Declare a custom humansize option struct
|
||||||
|
// See: https://docs.rs/humansize/1.0.2/humansize/file_size_opts/struct.FileSizeOpts.html
|
||||||
|
Arc::new(size_opts::FileSizeOpts {
|
||||||
|
divider: size_opts::Kilo::Binary,
|
||||||
|
units: size_opts::Kilo::Decimal,
|
||||||
|
decimal_places: 0,
|
||||||
|
decimal_zeroes: 0,
|
||||||
|
fixed_at: size_opts::FixedAt::No,
|
||||||
|
long_units: false,
|
||||||
|
space: true,
|
||||||
|
suffix: "",
|
||||||
|
allow_negative: false,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct EpisodeWidget {
|
pub struct EpisodeWidget {
|
||||||
pub container: gtk::Box,
|
pub container: gtk::Box,
|
||||||
@ -35,7 +47,7 @@ pub struct EpisodeWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct InfoLabels {
|
struct InfoLabels {
|
||||||
container: gtk::Box,
|
container: gtk::Box,
|
||||||
title: gtk::Label,
|
title: gtk::Label,
|
||||||
date: gtk::Label,
|
date: gtk::Label,
|
||||||
@ -48,7 +60,7 @@ pub struct InfoLabels {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Buttons {
|
struct Buttons {
|
||||||
container: gtk::ButtonBox,
|
container: gtk::ButtonBox,
|
||||||
play: gtk::Button,
|
play: gtk::Button,
|
||||||
download: gtk::Button,
|
download: gtk::Button,
|
||||||
@ -124,24 +136,6 @@ impl InfoLabels {
|
|||||||
|
|
||||||
// Set the size label of the episode widget.
|
// Set the size label of the episode widget.
|
||||||
fn set_size(&self, bytes: Option<i32>) {
|
fn set_size(&self, bytes: Option<i32>) {
|
||||||
lazy_static! {
|
|
||||||
static ref SIZE_OPTS: Arc<size_opts::FileSizeOpts> = {
|
|
||||||
// Declare a custom humansize option struct
|
|
||||||
// See: https://docs.rs/humansize/1.0.2/humansize/file_size_opts/struct.FileSizeOpts.html
|
|
||||||
Arc::new(size_opts::FileSizeOpts {
|
|
||||||
divider: size_opts::Kilo::Binary,
|
|
||||||
units: size_opts::Kilo::Decimal,
|
|
||||||
decimal_places: 0,
|
|
||||||
decimal_zeroes: 0,
|
|
||||||
fixed_at: size_opts::FixedAt::No,
|
|
||||||
long_units: false,
|
|
||||||
space: true,
|
|
||||||
suffix: "",
|
|
||||||
allow_negative: false,
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the bytes to a String label
|
// Convert the bytes to a String label
|
||||||
let size = || -> Option<String> {
|
let size = || -> Option<String> {
|
||||||
let s = bytes?;
|
let s = bytes?;
|
||||||
@ -215,7 +209,9 @@ impl EpisodeWidget {
|
|||||||
pub fn new(episode: EpisodeWidgetQuery, sender: &Sender<Action>) -> Rc<Self> {
|
pub fn new(episode: EpisodeWidgetQuery, sender: &Sender<Action>) -> Rc<Self> {
|
||||||
let widget = Rc::new(Self::default());
|
let widget = Rc::new(Self::default());
|
||||||
widget.info.init(&episode);
|
widget.info.init(&episode);
|
||||||
Self::determine_buttons_state(&widget, &episode, sender);
|
Self::determine_buttons_state(&widget, &episode, sender)
|
||||||
|
.map_err(|err| error!("Error: {}", err))
|
||||||
|
.ok();
|
||||||
widget
|
widget
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,7 +294,23 @@ impl EpisodeWidget {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(prog) = active_dl()? {
|
if let Some(prog) = active_dl()? {
|
||||||
// FIXME: Add again the callback ugly hack that makes things work somehow
|
// set a callback that will update the state when the download finishes
|
||||||
|
let callback = clone!(widget, sender => move || {
|
||||||
|
if let Ok(guard) = manager::ACTIVE_DOWNLOADS.read() {
|
||||||
|
if !guard.contains_key(&id) {
|
||||||
|
if let Ok(ep) = dbqueries::get_episode_widget_from_rowid(id) {
|
||||||
|
Self::determine_buttons_state(&widget, &ep, &sender)
|
||||||
|
.map_err(|err| error!("Error: {}", err))
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
return glib::Continue(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glib::Continue(true)
|
||||||
|
});
|
||||||
|
gtk::timeout_add(250, callback);
|
||||||
|
|
||||||
// Wire the cancel button
|
// Wire the cancel button
|
||||||
widget
|
widget
|
||||||
@ -343,7 +355,7 @@ impl EpisodeWidget {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(path) = episode.local_uri() {
|
if episode.local_uri().is_some() {
|
||||||
// Change the widget layout/state
|
// Change the widget layout/state
|
||||||
widget.state_playable();
|
widget.state_playable();
|
||||||
|
|
||||||
@ -390,54 +402,6 @@ impl EpisodeWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn determine_media_state(
|
|
||||||
media_machine: &Rc<RefCell<MediaMachine>>,
|
|
||||||
episode: &EpisodeWidgetQuery,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let id = episode.rowid();
|
|
||||||
let active_dl = || -> Result<Option<_>, Error> {
|
|
||||||
let m = manager::ACTIVE_DOWNLOADS
|
|
||||||
.read()
|
|
||||||
.map_err(|_| format_err!("Failed to get a lock on the mutex."))?;
|
|
||||||
|
|
||||||
Ok(m.get(&id).cloned())
|
|
||||||
}()?;
|
|
||||||
|
|
||||||
let mut lock = media_machine.try_borrow_mut()?;
|
|
||||||
take_mut::take(lock.deref_mut(), |media| {
|
|
||||||
media.determine_state(
|
|
||||||
episode.length(),
|
|
||||||
active_dl.is_some(),
|
|
||||||
episode.local_uri().is_some(),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Show or hide the play/delete/download buttons upon widget initialization.
|
|
||||||
if let Some(prog) = active_dl {
|
|
||||||
// set a callback that will update the state when the download finishes
|
|
||||||
let id = episode.rowid();
|
|
||||||
let callback = clone!(media_machine => move || {
|
|
||||||
if let Ok(guard) = manager::ACTIVE_DOWNLOADS.read() {
|
|
||||||
if !guard.contains_key(&id) {
|
|
||||||
if let Ok(ep) = dbqueries::get_episode_widget_from_rowid(id) {
|
|
||||||
determine_media_state(&media_machine, &ep)
|
|
||||||
.map_err(|err| error!("Error: {}", err))
|
|
||||||
.map_err(|_| error!("Could not determine Media State"))
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
return glib::Continue(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glib::Continue(true)
|
|
||||||
});
|
|
||||||
gtk::timeout_add(250, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_download_clicked(ep: &EpisodeWidgetQuery, sender: &Sender<Action>) -> Result<(), Error> {
|
fn on_download_clicked(ep: &EpisodeWidgetQuery, sender: &Sender<Action>) -> Result<(), Error> {
|
||||||
let pd = dbqueries::get_podcast_from_id(ep.podcast_id())?;
|
let pd = dbqueries::get_podcast_from_id(ep.podcast_id())?;
|
||||||
let download_fold = get_download_folder(&pd.title())?;
|
let download_fold = get_download_folder(&pd.title())?;
|
||||||
|
|||||||
@ -1,353 +0,0 @@
|
|||||||
// TODO: Things that should be done.
|
|
||||||
//
|
|
||||||
// * Wherever there's a function that take 2 or more arguments of the same type,
|
|
||||||
// eg: fn new(total_size: gtk::Label, local_size: gtk::Label ..)
|
|
||||||
// Wrap the types into Struct-tuples and imple deref so it won't be possible to pass
|
|
||||||
// the wrong argument to the wrong position.
|
|
||||||
|
|
||||||
use gtk;
|
|
||||||
|
|
||||||
use gtk::prelude::*;
|
|
||||||
use humansize::{file_size_opts as size_opts, FileSize};
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref SIZE_OPTS: Arc<size_opts::FileSizeOpts> = {
|
|
||||||
// Declare a custom humansize option struct
|
|
||||||
// See: https://docs.rs/humansize/1.0.2/humansize/file_size_opts/struct.FileSizeOpts.html
|
|
||||||
Arc::new(size_opts::FileSizeOpts {
|
|
||||||
divider: size_opts::Kilo::Binary,
|
|
||||||
units: size_opts::Kilo::Decimal,
|
|
||||||
decimal_places: 0,
|
|
||||||
decimal_zeroes: 0,
|
|
||||||
fixed_at: size_opts::FixedAt::No,
|
|
||||||
long_units: false,
|
|
||||||
space: true,
|
|
||||||
suffix: "",
|
|
||||||
allow_negative: false,
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Shown;
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Hidden;
|
|
||||||
|
|
||||||
pub trait Visibility {}
|
|
||||||
|
|
||||||
impl Visibility for Shown {}
|
|
||||||
impl Visibility for Hidden {}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Size<S> {
|
|
||||||
size: gtk::Label,
|
|
||||||
separator: gtk::Label,
|
|
||||||
state: S,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> Size<S> {
|
|
||||||
fn set_size(self, s: &str) -> Size<Shown> {
|
|
||||||
self.size.set_text(s);
|
|
||||||
self.size.show();
|
|
||||||
self.separator.show();
|
|
||||||
Size {
|
|
||||||
size: self.size,
|
|
||||||
separator: self.separator,
|
|
||||||
state: Shown {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://play.rust-lang.org/?gist=1acffaf62743eeb85be1ae6ecf474784&version=stable
|
|
||||||
// It might be possible to make a generic definition with Specialization.
|
|
||||||
// https://github.com/rust-lang/rust/issues/31844
|
|
||||||
fn into_shown(self) -> Size<Shown> {
|
|
||||||
self.size.show();
|
|
||||||
self.separator.show();
|
|
||||||
|
|
||||||
Size {
|
|
||||||
size: self.size,
|
|
||||||
separator: self.separator,
|
|
||||||
state: Shown {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_hidden(self) -> Size<Hidden> {
|
|
||||||
self.size.hide();
|
|
||||||
self.separator.hide();
|
|
||||||
|
|
||||||
Size {
|
|
||||||
size: self.size,
|
|
||||||
separator: self.separator,
|
|
||||||
state: Hidden {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pub trait Playable {}
|
|
||||||
|
|
||||||
// impl Playable for Download {}
|
|
||||||
// impl Playable for Play {}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Download;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Play;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
// FIXME: Needs better name.
|
|
||||||
// Should each button also has it's own type and machine?
|
|
||||||
pub struct DownloadPlay<S> {
|
|
||||||
play: gtk::Button,
|
|
||||||
download: gtk::Button,
|
|
||||||
state: S,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> DownloadPlay<S> {
|
|
||||||
// https://play.rust-lang.org/?gist=1acffaf62743eeb85be1ae6ecf474784&version=stable // It might be possible to make a generic definition with Specialization.
|
|
||||||
// https://github.com/rust-lang/rust/issues/31844
|
|
||||||
fn into_playable(self) -> DownloadPlay<Play> {
|
|
||||||
self.play.show();
|
|
||||||
self.download.hide();
|
|
||||||
|
|
||||||
DownloadPlay {
|
|
||||||
play: self.play,
|
|
||||||
download: self.download,
|
|
||||||
state: Play {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_fetchable(self) -> DownloadPlay<Download> {
|
|
||||||
self.play.hide();
|
|
||||||
self.download.show();
|
|
||||||
|
|
||||||
DownloadPlay {
|
|
||||||
play: self.play,
|
|
||||||
download: self.download,
|
|
||||||
state: Download {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_hidden(self) -> DownloadPlay<Hidden> {
|
|
||||||
self.play.hide();
|
|
||||||
self.download.hide();
|
|
||||||
|
|
||||||
DownloadPlay {
|
|
||||||
play: self.play,
|
|
||||||
download: self.download,
|
|
||||||
state: Hidden {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Progress<S> {
|
|
||||||
bar: gtk::ProgressBar,
|
|
||||||
cancel: gtk::Button,
|
|
||||||
local_size: gtk::Label,
|
|
||||||
prog_separator: gtk::Label,
|
|
||||||
state: S,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> Progress<S> {
|
|
||||||
fn into_shown(self) -> Progress<Shown> {
|
|
||||||
self.bar.show();
|
|
||||||
self.cancel.show();
|
|
||||||
self.local_size.show();
|
|
||||||
self.prog_separator.show();
|
|
||||||
|
|
||||||
Progress {
|
|
||||||
bar: self.bar,
|
|
||||||
cancel: self.cancel,
|
|
||||||
local_size: self.local_size,
|
|
||||||
prog_separator: self.prog_separator,
|
|
||||||
state: Shown {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_hidden(self) -> Progress<Hidden> {
|
|
||||||
self.bar.hide();
|
|
||||||
self.cancel.hide();
|
|
||||||
self.local_size.hide();
|
|
||||||
self.prog_separator.hide();
|
|
||||||
|
|
||||||
Progress {
|
|
||||||
bar: self.bar,
|
|
||||||
cancel: self.cancel,
|
|
||||||
local_size: self.local_size,
|
|
||||||
prog_separator: self.prog_separator,
|
|
||||||
state: Hidden {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Media<X, Y, Z> {
|
|
||||||
dl: DownloadPlay<X>,
|
|
||||||
size: Size<Y>,
|
|
||||||
progress: Progress<Z>,
|
|
||||||
}
|
|
||||||
|
|
||||||
type New<Y> = Media<Download, Y, Hidden>;
|
|
||||||
type Playable<Y> = Media<Play, Y, Hidden>;
|
|
||||||
type InProgress = Media<Hidden, Shown, Shown>;
|
|
||||||
|
|
||||||
impl<X, Y, Z> Media<X, Y, Z> {
|
|
||||||
fn hide_size(self) -> Media<X, Hidden, Z> {
|
|
||||||
Media {
|
|
||||||
dl: self.dl,
|
|
||||||
size: self.size.into_hidden(),
|
|
||||||
progress: self.progress,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_new(self, size: &str) -> New<Shown> {
|
|
||||||
Media {
|
|
||||||
dl: self.dl.into_fetchable(),
|
|
||||||
size: self.size.set_size(size),
|
|
||||||
progress: self.progress.into_hidden(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_new_without(self) -> New<Hidden> {
|
|
||||||
Media {
|
|
||||||
dl: self.dl.into_fetchable(),
|
|
||||||
size: self.size.into_hidden(),
|
|
||||||
progress: self.progress.into_hidden(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_playable(self, size: &str) -> Playable<Shown> {
|
|
||||||
Media {
|
|
||||||
dl: self.dl.into_playable(),
|
|
||||||
size: self.size.set_size(size),
|
|
||||||
progress: self.progress.into_hidden(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_playable_without(self) -> Playable<Hidden> {
|
|
||||||
Media {
|
|
||||||
dl: self.dl.into_playable(),
|
|
||||||
size: self.size.into_hidden(),
|
|
||||||
progress: self.progress.into_hidden(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<X, Z> Media<X, Shown, Z> {
|
|
||||||
fn into_progress(self) -> InProgress {
|
|
||||||
Media {
|
|
||||||
dl: self.dl.into_hidden(),
|
|
||||||
size: self.size.into_shown(),
|
|
||||||
progress: self.progress.into_shown(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<X, Z> Media<X, Hidden, Z> {
|
|
||||||
fn into_progress(self) -> InProgress {
|
|
||||||
Media {
|
|
||||||
dl: self.dl.into_hidden(),
|
|
||||||
size: self.size.set_size("Unkown"),
|
|
||||||
progress: self.progress.into_shown(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum ButtonsState {
|
|
||||||
New(Media<Download, Shown, Hidden>),
|
|
||||||
NewWithoutSize(Media<Download, Hidden, Hidden>),
|
|
||||||
Playable(Media<Play, Shown, Hidden>),
|
|
||||||
PlayableWithoutSize(Media<Play, Hidden, Hidden>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ButtonsState {
|
|
||||||
pub fn determine_state(self, size: Option<String>, is_downloaded: bool) -> Self {
|
|
||||||
use self::ButtonsState::*;
|
|
||||||
|
|
||||||
match (self, size, is_downloaded) {
|
|
||||||
// From whatever to New
|
|
||||||
(New(m), Some(s), false) => New(m.into_new(&s)),
|
|
||||||
(Playable(m), Some(s), false) => New(m.into_new(&s)),
|
|
||||||
|
|
||||||
(NewWithoutSize(m), Some(s), false) => New(m.into_new(&s)),
|
|
||||||
(PlayableWithoutSize(m), Some(s), false) => New(m.into_new(&s)),
|
|
||||||
|
|
||||||
// From whatever to Playable
|
|
||||||
(New(m), Some(s), true) => Playable(m.into_playable(&s)),
|
|
||||||
(Playable(m), Some(s), true) => Playable(m.into_playable(&s)),
|
|
||||||
|
|
||||||
(NewWithoutSize(m), Some(s), true) => Playable(m.into_playable(&s)),
|
|
||||||
(PlayableWithoutSize(m), Some(s), true) => Playable(m.into_playable(&s)),
|
|
||||||
|
|
||||||
// From whatever to NewWithoutSize
|
|
||||||
(New(m), None, false) => NewWithoutSize(m.hide_size()),
|
|
||||||
(Playable(m), None, false) => NewWithoutSize(m.into_new_without()),
|
|
||||||
|
|
||||||
(b @ NewWithoutSize(_), None, false) => b,
|
|
||||||
(PlayableWithoutSize(m), None, false) => NewWithoutSize(m.into_new_without()),
|
|
||||||
|
|
||||||
// From whatever to PlayableWithoutSize
|
|
||||||
(New(m), None, true) => PlayableWithoutSize(m.into_playable_without()),
|
|
||||||
(Playable(m), None, true) => PlayableWithoutSize(m.hide_size()),
|
|
||||||
|
|
||||||
(NewWithoutSize(val), None, true) => PlayableWithoutSize(val.into_playable_without()),
|
|
||||||
(b @ PlayableWithoutSize(_), None, true) => b,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_progress(self) -> InProgress {
|
|
||||||
use self::ButtonsState::*;
|
|
||||||
|
|
||||||
match self {
|
|
||||||
New(m) => m.into_progress(),
|
|
||||||
Playable(m) => m.into_progress(),
|
|
||||||
NewWithoutSize(m) => m.into_progress(),
|
|
||||||
PlayableWithoutSize(m) => m.into_progress(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum MediaMachine {
|
|
||||||
Initialized(ButtonsState),
|
|
||||||
InProgress(Media<Hidden, Shown, Shown>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MediaMachine {
|
|
||||||
pub fn determine_state(self, bytes: Option<i32>, is_active: bool, is_downloaded: bool) -> Self {
|
|
||||||
use self::ButtonsState::*;
|
|
||||||
use self::MediaMachine::*;
|
|
||||||
|
|
||||||
match (self, size_helper(bytes), is_downloaded, is_active) {
|
|
||||||
(Initialized(bttn), s, dl, false) => Initialized(bttn.determine_state(s, dl)),
|
|
||||||
(Initialized(bttn), _, _, true) => InProgress(bttn.into_progress()),
|
|
||||||
|
|
||||||
// Into New
|
|
||||||
(InProgress(m), Some(s), false, false) => Initialized(New(m.into_new(&s))),
|
|
||||||
(InProgress(m), None, false, false) => {
|
|
||||||
Initialized(NewWithoutSize(m.into_new_without()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Into Playable
|
|
||||||
(InProgress(m), Some(s), true, false) => Initialized(Playable(m.into_playable(&s))),
|
|
||||||
(InProgress(m), None, true, false) => {
|
|
||||||
Initialized(PlayableWithoutSize(m.into_playable_without()))
|
|
||||||
}
|
|
||||||
|
|
||||||
(i @ InProgress(_), _, _, _) => i,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_helper(bytes: Option<i32>) -> Option<String> {
|
|
||||||
let s = bytes?;
|
|
||||||
if s == 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
s.file_size(SIZE_OPTS.clone()).ok()
|
|
||||||
}
|
|
||||||
@ -2,7 +2,6 @@ mod aboutdialog;
|
|||||||
pub mod appnotif;
|
pub mod appnotif;
|
||||||
mod empty;
|
mod empty;
|
||||||
mod episode;
|
mod episode;
|
||||||
mod episode_states;
|
|
||||||
mod home_view;
|
mod home_view;
|
||||||
mod show;
|
mod show;
|
||||||
mod shows_view;
|
mod shows_view;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user