podcasts-gtk: Review ALL the strings!
This commit is contained in:
parent
a8a8c09b90
commit
bfdd6b5f7c
@ -48,7 +48,7 @@
|
|||||||
<object class="GtkLabel">
|
<object class="GtkLabel">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="label" translatable="yes">If you think this is an Error, Plese consider opening a bug report.</property>
|
<property name="label" translatable="yes">If you think this is an error, please consider opening a bug report.</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="dim-label"/>
|
<class name="dim-label"/>
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -175,7 +175,7 @@ Tobias Bernard
|
|||||||
<object class="GtkLabel" id="total_size">
|
<object class="GtkLabel" id="total_size">
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="no_show_all">True</property>
|
<property name="no_show_all">True</property>
|
||||||
<property name="label" translatable="yes">Calculating episode size...</property>
|
<property name="label" translatable="yes">Calculating episode size…</property>
|
||||||
<property name="single_line_mode">True</property>
|
<property name="single_line_mode">True</property>
|
||||||
<property name="track_visited_links">False</property>
|
<property name="track_visited_links">False</property>
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<menu id="menu">
|
<menu id="menu">
|
||||||
<section>
|
<section>
|
||||||
<item>
|
<item>
|
||||||
<attribute name="label" translatable="yes">_Check for new episodes</attribute>
|
<attribute name="label" translatable="yes">_Check for New Episodes</attribute>
|
||||||
<attribute name="action">win.refresh</attribute>
|
<attribute name="action">win.refresh</attribute>
|
||||||
<attribute name="accel"><primary>r</attribute>
|
<attribute name="accel"><primary>r</attribute>
|
||||||
</item>
|
</item>
|
||||||
@ -39,4 +39,4 @@
|
|||||||
</item>
|
</item>
|
||||||
</section>
|
</section>
|
||||||
</menu>
|
</menu>
|
||||||
</interface>
|
</interface>
|
||||||
|
|||||||
@ -88,7 +88,7 @@
|
|||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="tooltip_text" translatable="yes">Fast Forward 10 seconds</property>
|
<property name="tooltip_text" translatable="yes">Fast forward 10 seconds</property>
|
||||||
<property name="image">fast_forward</property>
|
<property name="image">fast_forward</property>
|
||||||
<property name="always_show_image">True</property>
|
<property name="always_show_image">True</property>
|
||||||
</object>
|
</object>
|
||||||
@ -254,7 +254,7 @@
|
|||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="tooltip_text" translatable="yes">Change the Playback speed</property>
|
<property name="tooltip_text" translatable="yes">Change the playback speed</property>
|
||||||
<property name="halign">center</property>
|
<property name="halign">center</property>
|
||||||
<property name="valign">center</property>
|
<property name="valign">center</property>
|
||||||
<property name="margin_left">6</property>
|
<property name="margin_left">6</property>
|
||||||
@ -269,7 +269,7 @@
|
|||||||
<object class="GtkLabel" id="rate_label">
|
<object class="GtkLabel" id="rate_label">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="label" translatable="yes">1.00x</property>
|
<property name="label" translatable="yes">1.00×</property>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
@ -313,7 +313,7 @@
|
|||||||
<property name="spacing">3</property>
|
<property name="spacing">3</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkRadioButton" id="rate_1_50">
|
<object class="GtkRadioButton" id="rate_1_50">
|
||||||
<property name="label" translatable="yes">1.50x</property>
|
<property name="label" translatable="yes">1.50×</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">False</property>
|
<property name="receives_default">False</property>
|
||||||
@ -331,7 +331,7 @@
|
|||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkRadioButton" id="rate_1_25">
|
<object class="GtkRadioButton" id="rate_1_25">
|
||||||
<property name="label" translatable="yes">1.25x</property>
|
<property name="label" translatable="yes">1.25×</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">False</property>
|
<property name="receives_default">False</property>
|
||||||
@ -349,7 +349,7 @@
|
|||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkRadioButton" id="normal_rate">
|
<object class="GtkRadioButton" id="normal_rate">
|
||||||
<property name="label" translatable="yes">1.00x</property>
|
<property name="label" translatable="yes">1.00×</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">False</property>
|
<property name="receives_default">False</property>
|
||||||
|
|||||||
@ -264,7 +264,7 @@
|
|||||||
<object class="GtkHeaderBar">
|
<object class="GtkHeaderBar">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="title">Preferences</property>
|
<property name="title" translatable="yes">Preferences</property>
|
||||||
<property name="show_close_button">True</property>
|
<property name="show_close_button">True</property>
|
||||||
<child>
|
<child>
|
||||||
<placeholder/>
|
<placeholder/>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<menu id="menu">
|
<menu id="menu">
|
||||||
<section>
|
<section>
|
||||||
<item>
|
<item>
|
||||||
<attribute name="label" translatable="yes">_Mark all episodes as played</attribute>
|
<attribute name="label" translatable="yes">_Mark All Episodes as Played</attribute>
|
||||||
<!-- <attribute name="action">win.refresh</attribute> -->
|
<!-- <attribute name="action">win.refresh</attribute> -->
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -17,4 +17,4 @@
|
|||||||
</item>
|
</item>
|
||||||
</section>
|
</section>
|
||||||
</menu>
|
</menu>
|
||||||
</interface>
|
</interface>
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="text" translatable="yes">Mark all as played</property>
|
<property name="text" translatable="yes">Mark All as Played</property>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
|||||||
@ -116,8 +116,8 @@ Tobias Bernard
|
|||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="halign">center</property>
|
<property name="halign">center</property>
|
||||||
<property name="valign">center</property>
|
<property name="valign">center</property>
|
||||||
<property name="label">This is embarrasing!
|
<property name="label" translatable="yes">This is embarrassing!
|
||||||
Sorry, we could not find a description for this Show.</property>
|
Sorry, we could not find a description for this show.</property>
|
||||||
<property name="use_markup">True</property>
|
<property name="use_markup">True</property>
|
||||||
<property name="justify">center</property>
|
<property name="justify">center</property>
|
||||||
<property name="wrap">True</property>
|
<property name="wrap">True</property>
|
||||||
|
|||||||
@ -101,7 +101,7 @@ impl App {
|
|||||||
None => return Inhibit(false),
|
None => return Inhibit(false),
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("Savign window position");
|
info!("Saving window position");
|
||||||
WindowGeometry::from_window(&window).write(&settings);
|
WindowGeometry::from_window(&window).write(&settings);
|
||||||
|
|
||||||
info!("Application is exiting");
|
info!("Application is exiting");
|
||||||
@ -111,7 +111,7 @@ impl App {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Create a content instance
|
// Create a content instance
|
||||||
let content = Content::new(&sender).expect("Content Initialization failed.");
|
let content = Content::new(&sender).expect("Content initialization failed.");
|
||||||
|
|
||||||
// Create the headerbar
|
// Create the headerbar
|
||||||
let header = Header::new(&content, &sender);
|
let header = Header::new(&content, &sender);
|
||||||
@ -274,7 +274,7 @@ impl App {
|
|||||||
pop.borrow_mut()
|
pop.borrow_mut()
|
||||||
.replace_widget(pd.clone())
|
.replace_widget(pd.clone())
|
||||||
.map_err(|err| error!("Failed to update ShowWidget: {}", err))
|
.map_err(|err| error!("Failed to update ShowWidget: {}", err))
|
||||||
.map_err(|_| error!("Failed ot update ShowWidget {}", pd.title()))
|
.map_err(|_| error!("Failed to update ShowWidget {}", pd.title()))
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
Action::ShowWidgetAnimated => {
|
Action::ShowWidgetAnimated => {
|
||||||
@ -330,7 +330,7 @@ impl App {
|
|||||||
textdomain("gnome-podcasts");
|
textdomain("gnome-podcasts");
|
||||||
|
|
||||||
let application = gtk::Application::new(APP_ID, gio::ApplicationFlags::empty())
|
let application = gtk::Application::new(APP_ID, gio::ApplicationFlags::empty())
|
||||||
.expect("Application Initialization failed...");
|
.expect("Application initialization failed...");
|
||||||
|
|
||||||
let weak_app = application.downgrade();
|
let weak_app = application.downgrade();
|
||||||
application.connect_startup(move |_| {
|
application.connect_startup(move |_| {
|
||||||
|
|||||||
@ -120,7 +120,7 @@ impl AddPopover {
|
|||||||
} else {
|
} else {
|
||||||
self.add.set_sensitive(false);
|
self.add.set_sensitive(false);
|
||||||
self.result
|
self.result
|
||||||
.set_label(i18n("You are already subscribed to this Show").as_str());
|
.set_label(i18n("You are already subscribed to this show").as_str());
|
||||||
self.result.show();
|
self.result.show();
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -128,7 +128,7 @@ impl AddPopover {
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.add.set_sensitive(false);
|
self.add.set_sensitive(false);
|
||||||
if !url.is_empty() {
|
if !url.is_empty() {
|
||||||
self.result.set_label(i18n("Invalid url").as_str());
|
self.result.set_label(i18n("Invalid URL").as_str());
|
||||||
self.result.show();
|
self.result.show();
|
||||||
error!("Error: {}", err);
|
error!("Error: {}", err);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ use std::sync::{Arc, Mutex, RwLock};
|
|||||||
// use std::path::PathBuf;
|
// use std::path::PathBuf;
|
||||||
|
|
||||||
// This is messy, undocumented and hacky af.
|
// This is messy, undocumented and hacky af.
|
||||||
// I am terrible at writting downloaders and download managers.
|
// I am terrible at writing downloaders and download managers.
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Progress {
|
pub(crate) struct Progress {
|
||||||
@ -81,7 +81,7 @@ pub(crate) fn add(id: i32, directory: String) -> Result<(), Error> {
|
|||||||
|
|
||||||
match ACTIVE_DOWNLOADS.write() {
|
match ACTIVE_DOWNLOADS.write() {
|
||||||
Ok(mut guard) => guard.insert(id, prog.clone()),
|
Ok(mut guard) => guard.insert(id, prog.clone()),
|
||||||
Err(err) => return Err(format_err!("ActiveDonwloads: {}.", err)),
|
Err(err) => return Err(format_err!("ActiveDownloads: {}.", err)),
|
||||||
};
|
};
|
||||||
|
|
||||||
DLPOOL.spawn(move || {
|
DLPOOL.spawn(move || {
|
||||||
@ -131,11 +131,11 @@ mod tests {
|
|||||||
let url = "https://web.archive.org/web/20180120110727if_/https://rss.acast.com/thetipoff";
|
let url = "https://web.archive.org/web/20180120110727if_/https://rss.acast.com/thetipoff";
|
||||||
// Create and index a source
|
// Create and index a source
|
||||||
let source = Source::from_url(url).unwrap();
|
let source = Source::from_url(url).unwrap();
|
||||||
// Copy it's id
|
// Copy its id
|
||||||
let sid = source.id();
|
let sid = source.id();
|
||||||
pipeline::run(vec![source], true).unwrap();
|
pipeline::run(vec![source], true).unwrap();
|
||||||
|
|
||||||
// Get the Podcast
|
// Get the podcast
|
||||||
let pd = dbqueries::get_podcast_from_source_id(sid).unwrap();
|
let pd = dbqueries::get_podcast_from_source_id(sid).unwrap();
|
||||||
let title = "Coming soon... The Tip Off";
|
let title = "Coming soon... The Tip Off";
|
||||||
// Get an episode
|
// Get an episode
|
||||||
@ -146,7 +146,7 @@ mod tests {
|
|||||||
add(episode.rowid(), download_fold).unwrap();
|
add(episode.rowid(), download_fold).unwrap();
|
||||||
assert_eq!(ACTIVE_DOWNLOADS.read().unwrap().len(), 1);
|
assert_eq!(ACTIVE_DOWNLOADS.read().unwrap().len(), 1);
|
||||||
|
|
||||||
// Give it soem time to download the file
|
// Give it some time to download the file
|
||||||
thread::sleep(time::Duration::from_secs(20));
|
thread::sleep(time::Duration::from_secs(20));
|
||||||
|
|
||||||
let final_path = format!("{}/{}.mp3", &fold2, episode.rowid());
|
let final_path = format!("{}/{}.mp3", &fold2, episode.rowid());
|
||||||
@ -162,11 +162,11 @@ mod tests {
|
|||||||
"https://web.archive.org/web/20180120104957if_/https://rss.art19.com/steal-the-stars";
|
"https://web.archive.org/web/20180120104957if_/https://rss.art19.com/steal-the-stars";
|
||||||
// Create and index a source
|
// Create and index a source
|
||||||
let source = Source::from_url(url).unwrap();
|
let source = Source::from_url(url).unwrap();
|
||||||
// Copy it's id
|
// Copy its id
|
||||||
let sid = source.id();
|
let sid = source.id();
|
||||||
pipeline::run(vec![source], true).unwrap();
|
pipeline::run(vec![source], true).unwrap();
|
||||||
|
|
||||||
// Get the Podcast
|
// Get the podcast
|
||||||
let pd = dbqueries::get_podcast_from_source_id(sid).unwrap();
|
let pd = dbqueries::get_podcast_from_source_id(sid).unwrap();
|
||||||
let title = "Introducing Steal the Stars";
|
let title = "Introducing Steal the Stars";
|
||||||
// Get an episode
|
// Get an episode
|
||||||
|
|||||||
@ -57,11 +57,11 @@ impl HomeStack {
|
|||||||
// Copy the vertical scrollbar adjustment from the old view.
|
// Copy the vertical scrollbar adjustment from the old view.
|
||||||
self.episodes
|
self.episodes
|
||||||
.save_alignment()
|
.save_alignment()
|
||||||
.map_err(|err| error!("Failed to set episodes_view allignment: {}", err))
|
.map_err(|err| error!("Failed to set episodes_view alignment: {}", err))
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
self.replace_view()?;
|
self.replace_view()?;
|
||||||
// Determine the actuall state.
|
// Determine the actual state.
|
||||||
self.determine_state().map_err(From::from)
|
self.determine_state().map_err(From::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ impl HomeStack {
|
|||||||
|
|
||||||
// Remove the old widget and add the new one
|
// Remove the old widget and add the new one
|
||||||
// during this the previous view is removed,
|
// during this the previous view is removed,
|
||||||
// and the visibile child fallsback to empty view.
|
// and the visible child falls back to empty view.
|
||||||
self.stack.remove(old);
|
self.stack.remove(old);
|
||||||
self.stack.add_named(&eps.container, "home");
|
self.stack.add_named(&eps.container, "home");
|
||||||
// Keep the previous state.
|
// Keep the previous state.
|
||||||
|
|||||||
@ -75,7 +75,7 @@ impl PopulatedStack {
|
|||||||
|
|
||||||
self.populated
|
self.populated
|
||||||
.save_alignment()
|
.save_alignment()
|
||||||
.map_err(|err| error!("Failed to set episodes_view allignment: {}", err))
|
.map_err(|err| error!("Failed to set episodes_view alignment: {}", err))
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
let pop = ShowsView::new(self.sender.clone());
|
let pop = ShowsView::new(self.sender.clone());
|
||||||
@ -90,7 +90,7 @@ impl PopulatedStack {
|
|||||||
pub(crate) fn replace_widget(&mut self, pd: Arc<Show>) -> Result<(), Error> {
|
pub(crate) fn replace_widget(&mut self, pd: Arc<Show>) -> Result<(), Error> {
|
||||||
let old = self.show.container.clone();
|
let old = self.show.container.clone();
|
||||||
|
|
||||||
// save the ShowWidget vertical scrollabar alignment
|
// save the ShowWidget vertical scrollbar alignment
|
||||||
self.show.show_id().map(|id| self.show.save_vadjustment(id));
|
self.show.show_id().map(|id| self.show.save_vadjustment(id));
|
||||||
|
|
||||||
let new = ShowWidget::new(pd, self.sender.clone());
|
let new = ShowWidget::new(pd, self.sender.clone());
|
||||||
|
|||||||
@ -10,7 +10,7 @@ pub(crate) fn init() -> Result<(), Error> {
|
|||||||
let gbytes = Bytes::from_static(res_bytes.as_ref());
|
let gbytes = Bytes::from_static(res_bytes.as_ref());
|
||||||
let resource = Resource::new_from_data(&gbytes)?;
|
let resource = Resource::new_from_data(&gbytes)?;
|
||||||
|
|
||||||
// Register the resource so It wont be dropped and will continue to live in
|
// Register the resource so it won't be dropped and will continue to live in
|
||||||
// memory.
|
// memory.
|
||||||
resources_register(&resource);
|
resources_register(&resource);
|
||||||
|
|
||||||
|
|||||||
@ -197,7 +197,7 @@ where
|
|||||||
// Refresh only specified feeds
|
// Refresh only specified feeds
|
||||||
pipeline::run(s, false)
|
pipeline::run(s, false)
|
||||||
.map_err(|err| error!("Error: {}", err))
|
.map_err(|err| error!("Error: {}", err))
|
||||||
.map_err(|_| error!("Error While trying to update the database."))
|
.map_err(|_| error!("Error while trying to update the database."))
|
||||||
.ok();
|
.ok();
|
||||||
} else {
|
} else {
|
||||||
// Refresh all the feeds
|
// Refresh all the feeds
|
||||||
@ -221,7 +221,7 @@ lazy_static! {
|
|||||||
static ref THREADPOOL: rayon::ThreadPool = rayon::ThreadPoolBuilder::new().build().unwrap();
|
static ref THREADPOOL: rayon::ThreadPool = rayon::ThreadPoolBuilder::new().build().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since gdk_pixbuf::Pixbuf is refference counted and every episode,
|
// Since gdk_pixbuf::Pixbuf is reference counted and every episode,
|
||||||
// use the cover of the Podcast Feed/Show, We can only create a Pixbuf
|
// use the cover of the Podcast Feed/Show, We can only create a Pixbuf
|
||||||
// cover per show and pass around the Rc pointer.
|
// cover per show and pass around the Rc pointer.
|
||||||
//
|
//
|
||||||
@ -235,7 +235,7 @@ pub(crate) fn set_image_from_path(
|
|||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// Check if there's an active download about this show cover.
|
// Check if there's an active download about this show cover.
|
||||||
// If there is, a callback will be set so this function will be called again.
|
// If there is, a callback will be set so this function will be called again.
|
||||||
// If the download succedes, there should be a quick return from the pixbuf cache_image
|
// If the download succeeds, there should be a quick return from the pixbuf cache_image
|
||||||
// If it fails another download will be scheduled.
|
// If it fails another download will be scheduled.
|
||||||
if let Ok(guard) = COVER_DL_REGISTRY.read() {
|
if let Ok(guard) = COVER_DL_REGISTRY.read() {
|
||||||
if guard.contains(&show_id) {
|
if guard.contains(&show_id) {
|
||||||
@ -249,7 +249,7 @@ pub(crate) fn set_image_from_path(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(hashmap) = CACHED_PIXBUFS.read() {
|
if let Ok(hashmap) = CACHED_PIXBUFS.read() {
|
||||||
// Check if the requested (cover + size) is already in the chache
|
// Check if the requested (cover + size) is already in the cache
|
||||||
// and if so do an early return after that.
|
// and if so do an early return after that.
|
||||||
if let Some(guard) = hashmap.get(&(show_id, size)) {
|
if let Some(guard) = hashmap.get(&(show_id, size)) {
|
||||||
guard
|
guard
|
||||||
@ -299,7 +299,7 @@ pub(crate) fn set_image_from_path(
|
|||||||
|
|
||||||
// FIXME: the signature should be `fn foo(s: Url) -> Result<Url, Error>`
|
// FIXME: the signature should be `fn foo(s: Url) -> Result<Url, Error>`
|
||||||
pub(crate) fn itunes_to_rss(url: &str) -> Result<String, Error> {
|
pub(crate) fn itunes_to_rss(url: &str) -> Result<String, Error> {
|
||||||
let id = itunes_id_from_url(url).ok_or_else(|| format_err!("Failed to find an Itunes ID."))?;
|
let id = itunes_id_from_url(url).ok_or_else(|| format_err!("Failed to find an iTunes ID."))?;
|
||||||
lookup_id(id)
|
lookup_id(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,7 +331,7 @@ pub(crate) fn on_import_clicked(window: >k::ApplicationWindow, sender: &Sender
|
|||||||
// TODO: It might be better to use a FileChooserNative widget.
|
// TODO: It might be better to use a FileChooserNative widget.
|
||||||
// Create the FileChooser Dialog
|
// Create the FileChooser Dialog
|
||||||
let dialog = FileChooserNative::new(
|
let dialog = FileChooserNative::new(
|
||||||
Some(i18n("Select the file from which to you want to Import Shows.").as_str()),
|
Some(i18n("Select the file from which to you want to import shows.").as_str()),
|
||||||
Some(window),
|
Some(window),
|
||||||
FileChooserAction::Open,
|
FileChooserAction::Open,
|
||||||
Some(i18n("_Import").as_str()),
|
Some(i18n("_Import").as_str()),
|
||||||
@ -349,24 +349,24 @@ pub(crate) fn on_import_clicked(window: >k::ApplicationWindow, sender: &Sender
|
|||||||
dialog.add_filter(&filter);
|
dialog.add_filter(&filter);
|
||||||
|
|
||||||
dialog.connect_response(clone!(sender => move |dialog, resp| {
|
dialog.connect_response(clone!(sender => move |dialog, resp| {
|
||||||
debug!("Dialong Response {}", resp);
|
debug!("Dialog Response {}", resp);
|
||||||
if resp == ResponseType::Accept.to_glib() {
|
if resp == ResponseType::Accept.to_glib() {
|
||||||
// TODO: Show an in-app notifictaion if the file can not be accessed
|
// TODO: Show an in-app notification if the file can not be accessed
|
||||||
if let Some(filename) = dialog.get_filename() {
|
if let Some(filename) = dialog.get_filename() {
|
||||||
debug!("File selected: {:?}", filename);
|
debug!("File selected: {:?}", filename);
|
||||||
|
|
||||||
rayon::spawn(clone!(sender => move || {
|
rayon::spawn(clone!(sender => move || {
|
||||||
// Parse the file and import the feeds
|
// Parse the file and import the feeds
|
||||||
if let Ok(sources) = opml::import_from_file(filename) {
|
if let Ok(sources) = opml::import_from_file(filename) {
|
||||||
// Refresh the succesfully parsed feeds to index them
|
// Refresh the successfully parsed feeds to index them
|
||||||
refresh(Some(sources), sender)
|
refresh(Some(sources), sender)
|
||||||
} else {
|
} else {
|
||||||
let text = i18n("Failed to parse the Imported file");
|
let text = i18n("Failed to parse the imported file");
|
||||||
sender.send(Action::ErrorNotification(text));
|
sender.send(Action::ErrorNotification(text));
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
let text = i18n("Selected File could not be accessed.");
|
let text = i18n("Selected file could not be accessed.");
|
||||||
sender.send(Action::ErrorNotification(text));
|
sender.send(Action::ErrorNotification(text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ use i18n::i18n;
|
|||||||
// https://gitlab.gnome.org/danigm/fractal/blob/503e311e22b9d7540089d735b92af8e8f93560c5/fractal-gtk/src/app.rs#L1883-1912
|
// https://gitlab.gnome.org/danigm/fractal/blob/503e311e22b9d7540089d735b92af8e8f93560c5/fractal-gtk/src/app.rs#L1883-1912
|
||||||
/// Given a `window` create and attach an `gtk::AboutDialog` to it.
|
/// Given a `window` create and attach an `gtk::AboutDialog` to it.
|
||||||
pub(crate) fn about_dialog(window: >k::ApplicationWindow) {
|
pub(crate) fn about_dialog(window: >k::ApplicationWindow) {
|
||||||
// Feel free to add yourself if you contribured.
|
// Feel free to add yourself if you contributed.
|
||||||
let authors = &[
|
let authors = &[
|
||||||
"Carlos Soriano",
|
"Carlos Soriano",
|
||||||
"Constantin Nickel",
|
"Constantin Nickel",
|
||||||
@ -28,7 +28,7 @@ pub(crate) fn about_dialog(window: >k::ApplicationWindow) {
|
|||||||
dialog.set_license_type(gtk::License::Gpl30);
|
dialog.set_license_type(gtk::License::Gpl30);
|
||||||
dialog.set_modal(true);
|
dialog.set_modal(true);
|
||||||
// TODO: make it show it fetches the commit hash from which it was built
|
// TODO: make it show it fetches the commit hash from which it was built
|
||||||
// and the version number is kept in sync automaticly
|
// and the version number is kept in sync automatically
|
||||||
dialog.set_version("0.4.4");
|
dialog.set_version("0.4.4");
|
||||||
dialog.set_program_name(&i18n("Podcasts"));
|
dialog.set_program_name(&i18n("Podcasts"));
|
||||||
// TODO: Need a wiki page first.
|
// TODO: Need a wiki page first.
|
||||||
|
|||||||
@ -86,7 +86,7 @@ impl InAppNotification {
|
|||||||
notif
|
notif
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a seperate method cause in order to get a nice animation
|
// This is a separate method cause in order to get a nice animation
|
||||||
// the revealer should be attached to something that displays it.
|
// the revealer should be attached to something that displays it.
|
||||||
// Previously we where doing it in the constructor, which had the result
|
// Previously we where doing it in the constructor, which had the result
|
||||||
// of the animation being skipped cause there was no parent widget to display it.
|
// of the animation being skipped cause there was no parent widget to display it.
|
||||||
|
|||||||
@ -78,7 +78,7 @@ impl InfoLabels {
|
|||||||
// Set the date label.
|
// Set the date label.
|
||||||
self.set_date(episode.epoch());
|
self.set_date(episode.epoch());
|
||||||
|
|
||||||
// Set the duaration label.
|
// Set the duration label.
|
||||||
self.set_duration(episode.duration());
|
self.set_duration(episode.duration());
|
||||||
|
|
||||||
// Set the total_size label.
|
// Set the total_size label.
|
||||||
@ -118,11 +118,11 @@ impl InfoLabels {
|
|||||||
|
|
||||||
// Set the duration label of the episode widget.
|
// Set the duration label of the episode widget.
|
||||||
fn set_duration(&self, seconds: Option<i32>) {
|
fn set_duration(&self, seconds: Option<i32>) {
|
||||||
// If lenght is provided
|
// If length is provided
|
||||||
if let Some(s) = seconds {
|
if let Some(s) = seconds {
|
||||||
// Convert seconds to minutes
|
// Convert seconds to minutes
|
||||||
let minutes = chrono::Duration::seconds(s.into()).num_minutes();
|
let minutes = chrono::Duration::seconds(s.into()).num_minutes();
|
||||||
// If the lenght is 1 or more minutes
|
// If the length is 1 or more minutes
|
||||||
if minutes != 0 {
|
if minutes != 0 {
|
||||||
// Set the label and show them.
|
// Set the label and show them.
|
||||||
self.duration
|
self.duration
|
||||||
@ -227,15 +227,15 @@ impl EpisodeWidget {
|
|||||||
|
|
||||||
// When the widget is attached to a parent,
|
// When the widget is attached to a parent,
|
||||||
// since it's a rust struct and not a widget the
|
// since it's a rust struct and not a widget the
|
||||||
// compiler drops the refference to it at the end of
|
// compiler drops the reference to it at the end of
|
||||||
// scope. That's cause we only attach the `self.container`
|
// scope. That's cause we only attach the `self.container`
|
||||||
// to the parent.
|
// to the parent.
|
||||||
//
|
//
|
||||||
// So this callback keeps a refference to the Rust Struct
|
// So this callback keeps a reference to the Rust Struct
|
||||||
// so the compiler won't drop it.
|
// so the compiler won't drop it.
|
||||||
//
|
//
|
||||||
// When the widget is detached from it's parent view this
|
// When the widget is detached from its parent view this
|
||||||
// callback runs freeing the last refference we were holding.
|
// callback runs freeing the last reference we were holding.
|
||||||
let foo = RefCell::new(Some(widget.clone()));
|
let foo = RefCell::new(Some(widget.clone()));
|
||||||
widget.container.connect_remove(move |_, _| {
|
widget.container.connect_remove(move |_, _| {
|
||||||
foo.borrow_mut().take();
|
foo.borrow_mut().take();
|
||||||
@ -348,7 +348,7 @@ impl EpisodeWidget {
|
|||||||
Ok(m.get(&id).cloned())
|
Ok(m.get(&id).cloned())
|
||||||
};
|
};
|
||||||
|
|
||||||
// State: InProggress
|
// State: InProgress
|
||||||
if let Some(prog) = active_dl()? {
|
if let Some(prog) = active_dl()? {
|
||||||
// set a callback that will update the state when the download finishes
|
// set a callback that will update the state when the download finishes
|
||||||
let callback = clone!(weak, sender => move || {
|
let callback = clone!(weak, sender => move || {
|
||||||
@ -442,7 +442,7 @@ impl EpisodeWidget {
|
|||||||
if let Ok(ep) = dbqueries::get_episode_widget_from_rowid(id) {
|
if let Ok(ep) = dbqueries::get_episode_widget_from_rowid(id) {
|
||||||
on_download_clicked(&ep, &sender)
|
on_download_clicked(&ep, &sender)
|
||||||
.and_then(|_| {
|
.and_then(|_| {
|
||||||
info!("Donwload started succesfully.");
|
info!("Download started successfully.");
|
||||||
Self::determine_buttons_state(&weak, &ep, &sender)
|
Self::determine_buttons_state(&weak, &ep, &sender)
|
||||||
})
|
})
|
||||||
.map_err(|err| error!("Error: {}", err))
|
.map_err(|err| error!("Error: {}", err))
|
||||||
|
|||||||
@ -116,7 +116,7 @@ impl PlayerTimes {
|
|||||||
self.duration.set_text(&format_duration(seconds as u32));
|
self.duration.set_text(&format_duration(seconds as u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the `gtk::SclaeBar` when the pipeline position is changed.
|
/// Update the `gtk::Scale` bar when the pipeline position is changed.
|
||||||
pub(crate) fn on_position_updated(&self, position: Position) {
|
pub(crate) fn on_position_updated(&self, position: Position) {
|
||||||
let seconds = position.seconds().map(|v| v as f64).unwrap_or(0.0);
|
let seconds = position.seconds().map(|v| v as f64).unwrap_or(0.0);
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ fn format_duration(seconds: u32) -> String {
|
|||||||
if seconds >= 3600 {
|
if seconds >= 3600 {
|
||||||
time.format("%T").to_string()
|
time.format("%T").to_string()
|
||||||
} else {
|
} else {
|
||||||
time.format("%M:%S").to_string()
|
time.format("%M∶%S").to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +301,7 @@ impl PlayerWidget {
|
|||||||
sender.send(Action::ErrorNotification(s));
|
sender.send(Action::ErrorNotification(s));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// The followign callbacks require `Send` but are handled by the gtk main loop
|
// The following callbacks require `Send` but are handled by the gtk main loop
|
||||||
let weak = Fragile::new(Rc::downgrade(s));
|
let weak = Fragile::new(Rc::downgrade(s));
|
||||||
|
|
||||||
// Update the duration label and the slider
|
// Update the duration label and the slider
|
||||||
@ -351,7 +351,7 @@ impl PlayerWidget {
|
|||||||
|
|
||||||
fn on_rate_changed(&self, rate: f64) {
|
fn on_rate_changed(&self, rate: f64) {
|
||||||
self.set_playback_rate(rate);
|
self.set_playback_rate(rate);
|
||||||
self.rate.label.set_text(&format!("{:.2}x", rate));
|
self.rate.label.set_text(&format!("{:.2}×", rate));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reveal(&self) {
|
fn reveal(&self) {
|
||||||
|
|||||||
@ -82,13 +82,13 @@ impl ShowWidget {
|
|||||||
utils::set_image_from_path(&self.cover, pd.id(), 256)
|
utils::set_image_from_path(&self.cover, pd.id(), 256)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the descripton text.
|
/// Set the description text.
|
||||||
fn set_description(&self, text: &str) {
|
fn set_description(&self, text: &str) {
|
||||||
self.description
|
self.description
|
||||||
.set_markup(html2text::from_read(text.as_bytes(), 70).trim());
|
.set_markup(html2text::from_read(text.as_bytes(), 70).trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save the scrollabar vajustment to the cache.
|
/// Save the scrollbar adjustment to the cache.
|
||||||
pub(crate) fn save_vadjustment(&self, oldid: i32) -> Result<(), Error> {
|
pub(crate) fn save_vadjustment(&self, oldid: i32) -> Result<(), Error> {
|
||||||
if let Ok(mut guard) = SHOW_WIDGET_VALIGNMENT.lock() {
|
if let Ok(mut guard) = SHOW_WIDGET_VALIGNMENT.lock() {
|
||||||
let adj = self
|
let adj = self
|
||||||
@ -109,7 +109,7 @@ impl ShowWidget {
|
|||||||
.map_err(|err| format_err!("Failed to lock widget align mutex: {}", err))?;
|
.map_err(|err| format_err!("Failed to lock widget align mutex: {}", err))?;
|
||||||
|
|
||||||
if let Some((oldid, ref fragile)) = *guard {
|
if let Some((oldid, ref fragile)) = *guard {
|
||||||
// Only copy the old scrollbar if both widget's represent the same podcast.
|
// Only copy the old scrollbar if both widgets represent the same podcast.
|
||||||
debug!("PID: {}", pd.id());
|
debug!("PID: {}", pd.id());
|
||||||
debug!("OLDID: {}", oldid);
|
debug!("OLDID: {}", oldid);
|
||||||
if pd.id() != oldid {
|
if pd.id() != oldid {
|
||||||
|
|||||||
@ -122,7 +122,7 @@ fn dim_titles(episodes: >k::ListBox) -> Option<()> {
|
|||||||
|
|
||||||
fn mark_all_watched(pd: &Show, sender: &Sender<Action>) -> Result<(), Error> {
|
fn mark_all_watched(pd: &Show, sender: &Sender<Action>) -> Result<(), Error> {
|
||||||
dbqueries::update_none_to_played_now(pd)?;
|
dbqueries::update_none_to_played_now(pd)?;
|
||||||
// Not all widgets migth have been loaded when the mark_all is hit
|
// Not all widgets might have been loaded when the mark_all is hit
|
||||||
// So we will need to refresh again after it's done.
|
// So we will need to refresh again after it's done.
|
||||||
sender.send(Action::RefreshWidgetIfSame(pd.id()));
|
sender.send(Action::RefreshWidgetIfSame(pd.id()));
|
||||||
sender.send(Action::RefreshEpisodesView);
|
sender.send(Action::RefreshEpisodesView);
|
||||||
|
|||||||
@ -115,7 +115,7 @@ fn on_child_activate(child: >k::FlowBoxChild, sender: &Sender<Action>) -> Resu
|
|||||||
|
|
||||||
// This is such an ugly hack...
|
// This is such an ugly hack...
|
||||||
let id = WidgetExt::get_name(child)
|
let id = WidgetExt::get_name(child)
|
||||||
.ok_or_else(|| format_err!("Faild to get \"episodes\" child from the stack."))?
|
.ok_or_else(|| format_err!("Failed to get \"episodes\" child from the stack."))?
|
||||||
.parse::<i32>()?;
|
.parse::<i32>()?;
|
||||||
let pd = Arc::new(dbqueries::get_podcast_from_id(id)?);
|
let pd = Arc::new(dbqueries::get_podcast_from_id(id)?);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user