Skip to content

Commit

Permalink
#361: Add API message to check for app update
Browse files Browse the repository at this point in the history
  • Loading branch information
mtkennerly committed Aug 1, 2024
1 parent 26aab6a commit 19f35d9
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
and you can click the icon to display the notes.
The primary manifest does not (yet) contain any notes,
so this mainly applies to secondary manifest authors.
* CLI: The `api` command now supports a `checkAppUpdate` message.
* Fixed:
* CLI: Some commands would fail with relative path arguments.
* Changed:
Expand Down
36 changes: 36 additions & 0 deletions src/cli/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub enum Output {
#[serde(rename_all = "camelCase")]
pub enum Request {
FindTitle(request::FindTitle),
CheckAppUpdate(request::CheckAppUpdate),
}

/// A response to an individual request.
Expand All @@ -54,6 +55,7 @@ pub enum Request {
pub enum Response {
Error(response::Error),
FindTitle(response::FindTitle),
CheckAppUpdate(response::CheckAppUpdate),
}

pub mod request {
Expand Down Expand Up @@ -91,6 +93,11 @@ pub mod request {
/// With multiple values, they will be checked in the order given.
pub names: Vec<String>,
}

/// Check whether an application update is available.
#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
#[serde(default, rename_all = "camelCase")]
pub struct CheckAppUpdate {}
}

pub mod response {
Expand All @@ -109,6 +116,22 @@ pub mod response {
/// Any matching titles found.
pub titles: BTreeSet<String>,
}

#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
#[serde(default, rename_all = "camelCase")]
pub struct CheckAppUpdate {
/// An available update.
pub update: Option<AppUpdate>,
}

#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
#[serde(default, rename_all = "camelCase")]
pub struct AppUpdate {
/// New version number.
pub version: String,
/// Release URL to open in browser.
pub url: String,
}
}

fn parse_input(input: Option<String>) -> Result<Input, String> {
Expand Down Expand Up @@ -186,6 +209,19 @@ pub fn process(input: Option<String>, config: &Config, manifest: &Manifest) -> R

responses.push(Response::FindTitle(response::FindTitle { titles }));
}
Request::CheckAppUpdate(request::CheckAppUpdate {}) => match crate::metadata::Release::fetch_sync() {
Ok(release) => {
let update = release.is_update().then(|| response::AppUpdate {
version: release.version.to_string(),
url: release.url,
});

responses.push(Response::CheckAppUpdate(response::CheckAppUpdate { update }));
}
Err(e) => {
responses.push(Response::Error(response::Error { message: e.to_string() }));
}
},
}
}

Expand Down
6 changes: 2 additions & 4 deletions src/gui/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1362,10 +1362,8 @@ impl Application for App {

if previous_latest.as_ref() != Some(&release.version) {
// The latest available version has changed (or this is our first time checking)
if let Ok(current) = semver::Version::parse(*crate::VERSION) {
if release.version > current {
return self.show_modal(Modal::AppUpdate { release });
}
if release.is_update() {
return self.show_modal(Modal::AppUpdate { release });
}
}
}
Expand Down
35 changes: 35 additions & 0 deletions src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,39 @@ impl Release {
code => Err(format!("status code: {code:?}").into()),
}
}

pub fn fetch_sync() -> Result<Self, crate::prelude::AnyError> {
#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize)]
pub struct Response {
pub html_url: String,
pub tag_name: String,
}

let req = reqwest::blocking::Client::new()
.get(Self::URL)
.header(reqwest::header::USER_AGENT, &*crate::prelude::USER_AGENT);
let res = req.send()?;

match res.status() {
reqwest::StatusCode::OK => {
let bytes = res.bytes()?.to_vec();
let raw = String::from_utf8(bytes)?;
let parsed = serde_json::from_str::<Response>(&raw)?;

Ok(Self {
version: semver::Version::parse(parsed.tag_name.trim_start_matches('v'))?,
url: parsed.html_url,
})
}
code => Err(format!("status code: {code:?}").into()),
}
}

pub fn is_update(&self) -> bool {
if let Ok(current) = semver::Version::parse(*crate::VERSION) {
self.version > current
} else {
false
}
}
}

0 comments on commit 19f35d9

Please sign in to comment.