Skip to content

Commit

Permalink
fix(core): Handle network connection errors
Browse files Browse the repository at this point in the history
If a network connection cannot be stablished to fetch firmware changelogs, we will instead display the devices with or without those changelogs

Fixes #28
  • Loading branch information
mmstick committed Aug 13, 2019
1 parent c6e9c3c commit 64230ff
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 115 deletions.
13 changes: 13 additions & 0 deletions gtk/src/changelog.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
use gtk::prelude::*;
use std::borrow::Cow;

pub fn generate_widget_none() -> gtk::Box {
gtk::BoxBuilder::new()
.margin_start(48)
.margin_end(48)
.child(
&gtk::LabelBuilder::new()
.label("No changelog available")
.build()
.upcast::<gtk::Widget>()
)
.build()
}

pub fn generate_widget<I, S>(changelog: I, pad: bool) -> gtk::Box
where
S: AsRef<str>,
Expand Down
10 changes: 5 additions & 5 deletions gtk/src/dialogs/fwupd.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use super::{DialogData, FirmwareUpdateDialog};
use crate::{Entity, FirmwareEvent, FirmwareInfo, FwupdDevice, FwupdRelease};
use crate::{Entity, FirmwareEvent, FwupdDevice, FwupdRelease};
use gtk::{self, prelude::*};
use std::{collections::BTreeSet, sync::Arc};

pub(crate) struct FwupdDialogData {
pub entity: Entity,
pub device: Arc<FwupdDevice>,
pub releases: BTreeSet<FwupdRelease>,
pub shared: DialogData,
pub shared: DialogData,
pub latest: Box<str>,
}

pub(crate) fn fwupd_dialog(
Expand All @@ -16,11 +17,10 @@ pub(crate) fn fwupd_dialog(
has_battery: bool,
upgrade_button: bool,
) {
let &FwupdDialogData { entity, device, releases, shared } = &data;
let &DialogData { sender, stack, info } = &shared;
let &FwupdDialogData { entity, device, releases, latest, shared } = &data;
let &DialogData { sender, stack, .. } = &shared;

let response = if !upgrade_button || device.needs_reboot() {
let &FirmwareInfo { ref latest, .. } = &info;

let log_entries = releases
.iter()
Expand Down
8 changes: 4 additions & 4 deletions gtk/src/dialogs/system76.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
use super::{DialogData, FirmwareUpdateDialog};
use crate::{Entity, FirmwareEvent, FirmwareInfo, System76Changelog, System76Digest};
use crate::{Entity, FirmwareEvent, System76Changelog, System76Digest};
use gtk::{self, prelude::*};

#[cfg(feature = "system76")]
pub(crate) struct System76DialogData {
pub entity: Entity,
pub digest: System76Digest,
pub changelog: System76Changelog,
pub latest: Box<str>,
pub shared: DialogData,
}

#[cfg(feature = "system76")]
pub(crate) fn s76_system_dialog(data: &System76DialogData, upgradeable: bool, has_battery: bool) {
let &System76DialogData { entity, digest, changelog, shared } = &data;
let &DialogData { sender, stack, info } = &shared;
let &FirmwareInfo { latest, .. } = &info;
let &System76DialogData { entity, digest, changelog, latest, shared } = &data;
let &DialogData { sender, stack, .. } = &shared;

let log_entries = changelog.versions.iter().map(|version| {
(version.bios.as_ref(), version.description.as_ref().map_or("", |desc| desc.as_ref()))
Expand Down
4 changes: 2 additions & 2 deletions gtk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ impl FirmwareWidget {
Firmware(SystemScheduled) => reboot(),
// An event that occurs when System76 system firmware has been found.
#[cfg(feature = "system76")]
Firmware(S76System(info, digest, changelog)) => {
state.system76_system(info, digest, changelog)
Firmware(S76System(info, data)) => {
state.system76_system(info, data)
}
// An event that occurs when a Thelio I/O board was discovered.
#[cfg(feature = "system76")]
Expand Down
169 changes: 101 additions & 68 deletions gtk/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// TODO: Further abstract state from the UI, removing the need for Rc, with new component storages.

use crate::{dialogs::*, views::*, widgets::*, ActivateEvent, Event, UiEvent};
use firmware_manager::*;

Expand Down Expand Up @@ -110,6 +112,7 @@ impl State {
#[cfg(feature = "fwupd")]
pub fn fwupd(&mut self, signal: FwupdSignal) {
let FwupdSignal { info, device, upgradeable, releases } = signal;
let upgradeable = Rc::new(Cell::new(upgradeable));
let entity = self.entities.create();
let has_battery = self.has_battery;

Expand All @@ -120,40 +123,54 @@ impl State {
self.widgets.view_devices.device(&info)
};

let data = Rc::new(FwupdDialogData {
device: Arc::new(device),
releases,
entity,
shared: DialogData {
sender: self.sender.clone(),
stack: Rc::downgrade(&widget.stack),
info,
},
});
widget.stack.hide();

let data = match info.latest.clone() {
Some(latest) => {
let data = Rc::new(FwupdDialogData {
device: Arc::new(device),
releases,
entity,
latest,
shared: DialogData {
sender: self.sender.clone(),
stack: Rc::downgrade(&widget.stack),
info,
},
});

let upgradeable = Rc::new(Cell::new(upgradeable));
if upgradeable.get() {
let data = Rc::clone(&data);
let upgradeable = Rc::clone(&upgradeable);
widget.stack.show();
widget.connect_upgrade_clicked(move || {
fwupd_dialog(&data, upgradeable.get(), has_battery, true)
});
}

if upgradeable.get() {
let data = Rc::clone(&data);
let upgradeable = Rc::clone(&upgradeable);
widget.connect_upgrade_clicked(move || {
fwupd_dialog(&data, upgradeable.get(), has_battery, true)
});
} else {
widget.stack.hide();
}
Some(data)
}
None => None,
};

let sender = self.ui_sender.clone();
widget.connect_clicked(move |revealer| {
reveal(&revealer, &sender, entity, || {
let &FwupdDialogData { ref releases, .. } = &*data;

let log_entries = releases
.iter()
.rev()
.map(|release| (release.version.as_ref(), release.description.as_ref()));

crate::changelog::generate_widget(log_entries, true).upcast::<gtk::Container>()
let data = &data;
reveal(&revealer, &sender, entity, move || {
let widget = data.as_ref().map_or_else(
crate::changelog::generate_widget_none,
|data| {
let releases = &data.releases;
let log_entries = releases
.iter()
.rev()
.map(|release| (release.version.as_ref(), release.description.as_ref()));

crate::changelog::generate_widget(log_entries, true)
}
);

widget.upcast::<gtk::Container>()
});
});

Expand All @@ -168,51 +185,63 @@ impl State {
pub fn system76_system(
&mut self,
info: FirmwareInfo,
digest: System76Digest,
changelog: System76Changelog,
downloaded: Option<(System76Digest, System76Changelog)>,
) {
let widget = self.widgets.view_devices.system(&info);
widget.stack.hide();
let entity = self.entities.create();
self.entities.associate_system(entity);
let upgradeable = info.current != info.latest;

let upgradeable = Rc::new(Cell::new(info.latest.as_ref().map_or(false, |latest| latest.as_ref() != info.current.as_ref())));
let has_battery = self.has_battery;

let data = Rc::new(System76DialogData {
entity,
digest,
changelog,
shared: DialogData {
sender: self.sender.clone(),
stack: Rc::downgrade(&widget.stack),
info,
},
});
let latest = info.latest.clone();
let data = latest
.and_then(|latest| downloaded.map(|d| (d, latest)))
.map(|((digest, changelog), latest)| {
let data = Rc::new(System76DialogData {
entity,
digest,
latest,
changelog,
shared: DialogData {
sender: self.sender.clone(),
stack: Rc::downgrade(&widget.stack),
info,
},
});

let upgradeable = Rc::new(Cell::new(upgradeable));
if upgradeable.get() {
widget.stack.show();
let data = Rc::clone(&data);
let upgradeable = Rc::clone(&upgradeable);
widget.connect_upgrade_clicked(move || {
s76_system_dialog(&data, upgradeable.get(), has_battery);
});
}

if upgradeable.get() {
let data = Rc::clone(&data);
let upgradeable = Rc::clone(&upgradeable);
widget.connect_upgrade_clicked(move || {
s76_system_dialog(&data, upgradeable.get(), has_battery);
data
});
} else {
widget.stack.hide();
}

let sender = self.ui_sender.clone();
widget.connect_clicked(move |revealer| {
reveal(&revealer, &sender, entity, || {
let &System76DialogData { ref changelog, .. } = &*data;

let log_entries = changelog.versions.iter().map(|version| {
(
version.bios.as_ref(),
version.description.as_ref().map_or("N/A", |desc| desc.as_ref()),
)
});

crate::changelog::generate_widget(log_entries, true).upcast::<gtk::Container>()
let widget = if let Some(data) = data.as_ref() {
let changelog = &data.changelog;

let log_entries = changelog.versions.iter().map(|version| {
(
version.bios.as_ref(),
version.description.as_ref().map_or("N/A", |desc| desc.as_ref()),
)
});

crate::changelog::generate_widget(log_entries, true)
} else {
crate::changelog::generate_widget_none()
};

widget.upcast::<gtk::Container>()
})
});

Expand All @@ -224,19 +253,19 @@ impl State {

/// An event that occurs when a Thelio I/O board was discovered.
#[cfg(feature = "system76")]
pub fn thelio_io(&mut self, info: FirmwareInfo, digest: System76Digest) {
pub fn thelio_io(&mut self, info: FirmwareInfo, digest: Option<System76Digest>) {
let widget = self.widgets.view_devices.device(&info);
let entity = self.entities.create();

let upgradeable = info.current != info.latest;
let upgradeable = info.latest.as_ref().map_or(false, |latest| latest.as_ref() != info.current.as_ref());

let sender = self.sender.clone();
let tx_progress = self.progress_sender.clone();
let stack = Rc::downgrade(&widget.stack);
let latest: Rc<str> = Rc::from(info.latest);
let latest: Option<Rc<str>> = info.latest.map(Rc::from);

{
let latest = Rc::clone(&latest);
if let (Some(digest), Some(latest)) = (digest, latest.as_ref()) {
let latest = Rc::clone(latest);
widget.connect_upgrade_clicked(move || {
// Exchange the button for a progress bar.
if let Some(stack) = stack.upgrade() {
Expand All @@ -254,8 +283,12 @@ impl State {
let sender = self.ui_sender.clone();
widget.connect_clicked(move |revealer| {
reveal(&revealer, &sender, entity, || {
crate::changelog::generate_widget(iter::once((latest.as_ref(), "")), true)
.upcast::<gtk::Container>()
let widget = latest.as_ref().map_or_else(
|| crate::changelog::generate_widget_none(),
|latest| crate::changelog::generate_widget(iter::once((latest.as_ref(), "")), true)
);

widget.upcast::<gtk::Container>()
});
});
}
Expand Down
4 changes: 2 additions & 2 deletions notify/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ fn main() {
let event_handler = |event: FirmwareSignal| match event {
#[cfg(feature = "fwupd")]
FirmwareSignal::Fwupd(FwupdSignal { info, .. }) => {
if info.current != info.latest {
if info.latest.as_ref().map_or(false, |latest| latest.as_ref() == info.current.as_ref()) {
notify();
}
}
#[cfg(feature = "system76")]
FirmwareSignal::S76System(info, ..) | FirmwareSignal::ThelioIo(info, ..) => {
if info.current != info.latest {
if info.latest.as_ref().map_or(false, |latest| latest.as_ref() == info.current.as_ref()) {
notify();
}
}
Expand Down
Loading

0 comments on commit 64230ff

Please sign in to comment.