Headerbar: Added update indication.
This commit is contained in:
parent
bcc089bd82
commit
ce08d49107
@ -159,6 +159,37 @@
|
|||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="update_notification">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="no_show_all">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSpinner" id="update_spinner">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="padding">6</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="update_label">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Fetching new episodes</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="position">3</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
<child type="title">
|
<child type="title">
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
|||||||
@ -151,7 +151,7 @@
|
|||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="halign">center</property>
|
<property name="halign">center</property>
|
||||||
<property name="valign">center</property>
|
<property name="valign">center</property>
|
||||||
<property name="action_name">app.update</property>
|
<property name="action_name">app.refresh</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="destructive-action"/>
|
<class name="destructive-action"/>
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -66,8 +66,9 @@ impl App {
|
|||||||
pub fn setup_actions(&self) {
|
pub fn setup_actions(&self) {
|
||||||
let update = gio::SimpleAction::new("update", None);
|
let update = gio::SimpleAction::new("update", None);
|
||||||
let content = self.content.clone();
|
let content = self.content.clone();
|
||||||
|
let header = self.header.clone();
|
||||||
update.connect_activate(move |_, _| {
|
update.connect_activate(move |_, _| {
|
||||||
utils::refresh_feed(content.clone(), None);
|
utils::refresh_feed(content.clone(), header.clone(), None);
|
||||||
});
|
});
|
||||||
self.app_instance.add_action(&update);
|
self.app_instance.add_action(&update);
|
||||||
|
|
||||||
@ -97,23 +98,25 @@ impl App {
|
|||||||
|
|
||||||
pub fn setup_timed_callbacks(&self) {
|
pub fn setup_timed_callbacks(&self) {
|
||||||
let content = self.content.clone();
|
let content = self.content.clone();
|
||||||
|
let header = self.header.clone();
|
||||||
// Update 30 seconds after the Application is initialized.
|
// Update 30 seconds after the Application is initialized.
|
||||||
gtk::timeout_add_seconds(
|
gtk::timeout_add_seconds(
|
||||||
30,
|
30,
|
||||||
clone!(content => move || {
|
clone!(content => move || {
|
||||||
utils::refresh_feed(content.clone(), None);
|
utils::refresh_feed(content.clone(), header.clone(), None);
|
||||||
glib::Continue(false)
|
glib::Continue(false)
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let content = self.content.clone();
|
let content = self.content.clone();
|
||||||
|
let header = self.header.clone();
|
||||||
// Auto-updater, runs every hour.
|
// Auto-updater, runs every hour.
|
||||||
// TODO: expose the interval in which it run to a user setting.
|
// TODO: expose the interval in which it run to a user setting.
|
||||||
// TODO: show notifications.
|
// TODO: show notifications.
|
||||||
gtk::timeout_add_seconds(
|
gtk::timeout_add_seconds(
|
||||||
3600,
|
3600,
|
||||||
clone!(content => move || {
|
clone!(content => move || {
|
||||||
utils::refresh_feed(content.clone(), None);
|
utils::refresh_feed(content.clone(), header.clone(), None);
|
||||||
glib::Continue(true)
|
glib::Continue(true)
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -8,7 +8,7 @@ use std::rc::Rc;
|
|||||||
use utils;
|
use utils;
|
||||||
use content::Content;
|
use content::Content;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Header {
|
pub struct Header {
|
||||||
pub container: gtk::HeaderBar,
|
pub container: gtk::HeaderBar,
|
||||||
add_toggle: gtk::MenuButton,
|
add_toggle: gtk::MenuButton,
|
||||||
@ -16,6 +16,9 @@ pub struct Header {
|
|||||||
switch: gtk::StackSwitcher,
|
switch: gtk::StackSwitcher,
|
||||||
back_button: gtk::Button,
|
back_button: gtk::Button,
|
||||||
show_title: gtk::Label,
|
show_title: gtk::Label,
|
||||||
|
update_box: gtk::Box,
|
||||||
|
update_label: gtk::Label,
|
||||||
|
update_spinner: gtk::Spinner,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Header {
|
impl Default for Header {
|
||||||
@ -28,6 +31,9 @@ impl Default for Header {
|
|||||||
let switch: gtk::StackSwitcher = builder.get_object("switch").unwrap();
|
let switch: gtk::StackSwitcher = builder.get_object("switch").unwrap();
|
||||||
let back_button: gtk::Button = builder.get_object("back_button").unwrap();
|
let back_button: gtk::Button = builder.get_object("back_button").unwrap();
|
||||||
let show_title: gtk::Label = builder.get_object("show_title").unwrap();
|
let show_title: gtk::Label = builder.get_object("show_title").unwrap();
|
||||||
|
let update_box: gtk::Box = builder.get_object("update_notification").unwrap();
|
||||||
|
let update_label: gtk::Label = builder.get_object("update_label").unwrap();
|
||||||
|
let update_spinner: gtk::Spinner = builder.get_object("update_spinner").unwrap();
|
||||||
|
|
||||||
Header {
|
Header {
|
||||||
container: header,
|
container: header,
|
||||||
@ -36,6 +42,9 @@ impl Default for Header {
|
|||||||
switch,
|
switch,
|
||||||
back_button,
|
back_button,
|
||||||
show_title,
|
show_title,
|
||||||
|
update_box,
|
||||||
|
update_label,
|
||||||
|
update_spinner,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,8 +70,9 @@ impl Header {
|
|||||||
println!("{:?}", url.get_text());
|
println!("{:?}", url.get_text());
|
||||||
});
|
});
|
||||||
|
|
||||||
add_button.connect_clicked(clone!(content, add_popover, new_url => move |_| {
|
let header = Rc::new(self.clone());
|
||||||
on_add_bttn_clicked(content.clone(), &new_url);
|
add_button.connect_clicked(clone!(content, header, add_popover, new_url => move |_| {
|
||||||
|
on_add_bttn_clicked(content.clone(), header.clone(), &new_url);
|
||||||
|
|
||||||
// TODO: lock the button instead of hiding and add notification of feed added.
|
// TODO: lock the button instead of hiding and add notification of feed added.
|
||||||
// TODO: map the spinner
|
// TODO: map the spinner
|
||||||
@ -104,16 +114,30 @@ impl Header {
|
|||||||
pub fn set_show_title(&self, title: &str) {
|
pub fn set_show_title(&self, title: &str) {
|
||||||
self.show_title.set_text(title)
|
self.show_title.set_text(title)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn show_update_notification(&self) {
|
||||||
|
self.update_spinner.start();
|
||||||
|
self.update_box.show();
|
||||||
|
self.update_spinner.show();
|
||||||
|
self.update_label.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hide_update_notification(&self) {
|
||||||
|
self.update_spinner.stop();
|
||||||
|
self.update_box.hide();
|
||||||
|
self.update_spinner.hide();
|
||||||
|
self.update_label.hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_add_bttn_clicked(content: Rc<Content>, entry: >k::Entry) {
|
fn on_add_bttn_clicked(content: Rc<Content>, headerbar: Rc<Header>, entry: >k::Entry) {
|
||||||
let url = entry.get_text().unwrap_or_default();
|
let url = entry.get_text().unwrap_or_default();
|
||||||
let source = Source::from_url(&url);
|
let source = Source::from_url(&url);
|
||||||
|
|
||||||
if let Ok(s) = source {
|
if let Ok(s) = source {
|
||||||
info!("{:?} feed added", url);
|
info!("{:?} feed added", url);
|
||||||
// update the db
|
// update the db
|
||||||
utils::refresh_feed(content, Some(vec![s]));
|
utils::refresh_feed(content, headerbar, Some(vec![s]));
|
||||||
} else {
|
} else {
|
||||||
error!("Feed probably already exists.");
|
error!("Feed probably already exists.");
|
||||||
error!("Error: {:?}", source.unwrap_err());
|
error!("Error: {:?}", source.unwrap_err());
|
||||||
|
|||||||
@ -14,8 +14,9 @@ use std::rc::Rc;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use content::Content;
|
use content::Content;
|
||||||
|
use headerbar::Header;
|
||||||
|
|
||||||
type Foo = RefCell<Option<(Rc<Content>, Receiver<bool>)>>;
|
type Foo = RefCell<Option<(Rc<Content>, Rc<Header>, Receiver<bool>)>>;
|
||||||
|
|
||||||
// Create a thread local storage that will store the arguments to be transfered.
|
// Create a thread local storage that will store the arguments to be transfered.
|
||||||
thread_local!(static GLOBAL: Foo = RefCell::new(None));
|
thread_local!(static GLOBAL: Foo = RefCell::new(None));
|
||||||
@ -24,13 +25,15 @@ thread_local!(static GLOBAL: Foo = RefCell::new(None));
|
|||||||
/// If `source` is None, Fetches all the `Source` entries in the database and updates them.
|
/// If `source` is None, Fetches all the `Source` entries in the database and updates them.
|
||||||
/// `delay` represents the desired time in seconds for the thread to sleep before executing.
|
/// `delay` represents the desired time in seconds for the thread to sleep before executing.
|
||||||
/// When It's done,it queues up a `podcast_view` refresh.
|
/// When It's done,it queues up a `podcast_view` refresh.
|
||||||
pub fn refresh_feed(content: Rc<Content>, source: Option<Vec<Source>>) {
|
pub fn refresh_feed(content: Rc<Content>, headerbar: Rc<Header>, source: Option<Vec<Source>>) {
|
||||||
|
headerbar.show_update_notification();
|
||||||
|
|
||||||
// Create a async channel.
|
// Create a async channel.
|
||||||
let (sender, receiver) = channel();
|
let (sender, receiver) = channel();
|
||||||
|
|
||||||
// Pass the desired arguments into the Local Thread Storage.
|
// Pass the desired arguments into the Local Thread Storage.
|
||||||
GLOBAL.with(clone!(content => move |global| {
|
GLOBAL.with(clone!(content, headerbar => move |global| {
|
||||||
*global.borrow_mut() = Some((content.clone(), receiver));
|
*global.borrow_mut() = Some((content.clone(), headerbar.clone(), receiver));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
@ -51,9 +54,10 @@ pub fn refresh_feed(content: Rc<Content>, source: Option<Vec<Source>>) {
|
|||||||
|
|
||||||
fn refresh_everything() -> glib::Continue {
|
fn refresh_everything() -> glib::Continue {
|
||||||
GLOBAL.with(|global| {
|
GLOBAL.with(|global| {
|
||||||
if let Some((ref content, ref reciever)) = *global.borrow() {
|
if let Some((ref content, ref headerbar, ref reciever)) = *global.borrow() {
|
||||||
if reciever.try_recv().is_ok() {
|
if reciever.try_recv().is_ok() {
|
||||||
content.update();
|
content.update();
|
||||||
|
headerbar.hide_update_notification();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user