Skip to content

Commit e66d9c4

Browse files
authored
fix(gui-client): fix some papercuts (firezone#3769)
Fixes various small issues, including some of the issues in firezone#3768: - Clicking "About" or "Settings" no longer toggles a window between visible and hidden, it always shows and un-minimizes the window. So if it's minimized, it won't vanish, it will appear - Log message for vt100 failure is clearer - The "cancel sign-in" race was coincidentally already working as intended, but the code and comments are clarified. - Fix the asset name used to check for auto-updates (this cannot be end-to-end tested until we cut a new release of the clients on Github, not just a draft release) - Fix README to include Ubuntu instructions
1 parent c6ff885 commit e66d9c4

File tree

5 files changed

+99
-27
lines changed

5 files changed

+99
-27
lines changed

.github/workflows/cd.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ jobs:
249249
fail-fast: false
250250
# The matrix is 1x1 to match the style of build-push-linux-release-artifacts
251251
# In the future we could try to cross-compile aarch64-windows here.
252+
# Match with `updates.rs` in gui-client, `git grep WCPYPXZF`
252253
matrix:
253254
include:
254255
- runs-on: ubuntu-20.04

rust/gui-client/README.md

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1-
# windows-client
1+
# gui-client
22

3-
This crate houses a Windows GUI client.
3+
This crate houses a GUI client for Linux and Windows.
44

5-
## Setup
5+
## Setup (Ubuntu)
66

7-
This is the minimal toolchain needed to compile natively for x86_64 Windows:
7+
To compile natively for x86_64 Linux:
88

9-
1. [Install rustup](https://win.rustup.rs/x86_64) for Windows.
10-
1. Install [pnpm](https://pnpm.io/installation) for your platform.
9+
1. [Install rustup](https://rustup.rs/)
10+
1. Install [pnpm](https://pnpm.io/installation)
11+
1. `sudo apt-get install at-spi2-core gcc libwebkit2gtk-4.0-dev libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev pkg-config xvfb`
12+
13+
## Setup (Windows)
14+
15+
To compile natively for x86_64 Windows:
16+
17+
1. [Install rustup](https://rustup.rs/)
18+
1. Install [pnpm](https://pnpm.io/installation)
1119

1220
### Recommended IDE Setup
1321

@@ -25,10 +33,17 @@ and css is compiled properly before bundling the application.
2533
See the [`package.json`](./package.json) script for more details as to what's
2634
going on under the hood.
2735

28-
```powershell
36+
```bash
2937
# Builds a release exe
3038
pnpm build
3139

40+
# Linux:
41+
# The release exe, AppImage with bundled WebView, and deb package are up in the workspace.
42+
stat ../target/release/firezone
43+
stat ../target/release/bundle/appimage/*.AppImage
44+
stat ../target/release/bundle/deb/*.deb
45+
46+
# Windows:
3247
# The release exe and MSI installer should be up in the workspace.
3348
# The exe can run without being installed
3449
stat ../target/release/Firezone.exe
@@ -56,6 +71,8 @@ The app's config and logs will be stored at
5671

5772
## Platform support
5873

74+
Ubuntu 20.04 and newer is supported.
75+
5976
Tauri says it should work on Windows 10, Version 1803 and up. Older versions may
6077
work if you
6178
[manually install WebView2](https://tauri.app/v1/guides/getting-started/prerequisites#2-webview2)

rust/gui-client/src-tauri/src/client/gui.rs

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ pub(crate) fn run(cli: &client::Cli) -> Result<(), Error> {
183183
if let tauri::WindowEvent::CloseRequested { api, .. } = event.event() {
184184
// Keep the frontend running but just hide this webview
185185
// Per https://tauri.app/v1/guides/features/system-tray/#preventing-the-app-from-closing
186+
// Closing the window fully seems to deallocate it or something.
186187

187188
event.window().hide().unwrap();
188189
api.prevent_close();
@@ -201,6 +202,7 @@ pub(crate) fn run(cli: &client::Cli) -> Result<(), Error> {
201202
.system_tray(tray)
202203
.on_system_tray_event(|app, event| {
203204
if let SystemTrayEvent::MenuItemClick { id, .. } = event {
205+
tracing::debug!(?id, "SystemTrayEvent::MenuItemClick");
204206
let event = match TrayMenuEvent::from_str(&id) {
205207
Ok(x) => x,
206208
Err(e) => {
@@ -599,13 +601,24 @@ impl Controller {
599601
.handle_deep_link(&url)
600602
.await
601603
.context("Couldn't handle deep link")?,
604+
Req::SystemTrayMenu(TrayMenuEvent::CancelSignIn) => {
605+
if self.session.is_some() {
606+
// If the user opened the menu, then sign-in completed, then they
607+
// click "cancel sign in", don't sign out - They can click Sign Out
608+
// if they want to sign out. "Cancel" may mean "Give up waiting,
609+
// but if you already got in, don't make me sign in all over again."
610+
//
611+
// Also, by amazing coincidence, it doesn't work in Tauri anyway.
612+
// We'd have to reuse the `sign_out` ID to make it work.
613+
tracing::info!("This can never happen. Tauri doesn't pass us a system tray event if the menu no longer has any item with that ID.");
614+
} else {
615+
tracing::info!("Calling `sign_out` to cancel sign-in");
616+
self.sign_out()?;
617+
}
618+
}
602619
Req::SystemTrayMenu(TrayMenuEvent::ToggleWindow(window)) => {
603620
self.toggle_window(window)?
604621
}
605-
Req::SystemTrayMenu(TrayMenuEvent::CancelSignIn | TrayMenuEvent::SignOut) => {
606-
tracing::info!("User signed out or canceled sign-in");
607-
self.sign_out()?;
608-
}
609622
Req::SystemTrayMenu(TrayMenuEvent::Resource { id }) => self
610623
.copy_resource(&id)
611624
.context("Couldn't copy resource to clipboard")?,
@@ -620,6 +633,10 @@ impl Controller {
620633
)?;
621634
}
622635
}
636+
Req::SystemTrayMenu(TrayMenuEvent::SignOut) => {
637+
tracing::info!("User asked to sign out");
638+
self.sign_out()?;
639+
}
623640
Req::SystemTrayMenu(TrayMenuEvent::Quit) => {
624641
bail!("Impossible error: `Quit` should be handled before this")
625642
}
@@ -705,7 +722,7 @@ impl Controller {
705722
} else {
706723
// Might just be because we got a double sign-out or
707724
// the user canceled the sign-in or something innocent.
708-
tracing::warn!("tried to sign out but there's no session");
725+
tracing::info!("Tried to sign out but there's no session, cancelled sign-in");
709726
}
710727
self.refresh_system_tray_menu()?;
711728
Ok(())
@@ -722,12 +739,8 @@ impl Controller {
722739
.get_window(id)
723740
.ok_or_else(|| anyhow!("getting handle to `{id}` window"))?;
724741

725-
if win.is_visible()? {
726-
// If we close the window here, we can't re-open it, we'd have to fully re-create it. Not needed for MVP - We agreed 100 MB is fine for the GUI client.
727-
win.hide()?;
728-
} else {
729-
win.show()?;
730-
}
742+
win.show()?;
743+
win.unminimize()?;
731744
Ok(())
732745
}
733746
}

rust/gui-client/src-tauri/src/client/logging.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub(crate) fn setup(log_filter: &str) -> Result<Handles, Error> {
5050
if let Err(error) = output_vt100::try_init() {
5151
tracing::warn!(
5252
?error,
53-
"Failed to init vt100 terminal colors (expected in CI)"
53+
"Failed to init vt100 terminal colors (expected in release builds and in CI)"
5454
);
5555
}
5656
LogTracer::init()?;

rust/gui-client/src-tauri/src/client/updates.rs

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ impl Release {
2323
let ReleaseDetails { assets, tag_name } = serde_json::from_str(s)?;
2424
let asset = assets
2525
.into_iter()
26-
.find(|asset| asset.name == MSI_ASSET_NAME)
26+
.find(|asset| asset.name == ASSET_NAME)
2727
.ok_or(Error::NoSuchAsset)?;
2828

2929
Ok(Release {
@@ -51,7 +51,7 @@ pub(crate) enum Error {
5151
HttpStatus(reqwest::StatusCode),
5252
#[error(transparent)]
5353
JsonParse(#[from] serde_json::Error),
54-
#[error("No such asset `{MSI_ASSET_NAME}` in the latest release")]
54+
#[error("No such asset `{ASSET_NAME}` in the latest release")]
5555
NoSuchAsset,
5656
#[error("Our own semver in the exe is invalid, this should be impossible")]
5757
OurVersionIsInvalid(semver::Error),
@@ -67,9 +67,12 @@ const GITHUB_API_VERSION: &str = "2022-11-28";
6767

6868
/// The name of the Windows MSI asset.
6969
///
70-
/// This ultimately comes from `cd.yml`
71-
// TODO: Remove 'windows'
72-
const MSI_ASSET_NAME: &str = "firezone-gui-client-windows-x64.msi";
70+
/// This ultimately comes from `cd.yml`, `git grep WCPYPXZF`
71+
#[cfg(target_os = "linux")]
72+
const ASSET_NAME: &str = "firezone-linux-gui-client_amd64.AppImage";
73+
74+
#[cfg(target_os = "windows")]
75+
const ASSET_NAME: &str = "firezone-windows-client-x64.msi";
7376

7477
/// Returns the latest release, even if ours is already newer
7578
pub(crate) async fn check() -> Result<Release, Error> {
@@ -166,11 +169,45 @@ mod tests {
166169
"created_at": "2024-01-24T00:23:23Z",
167170
"published_at": "2024-01-24T04:34:44Z",
168171
"assets": [
172+
{
173+
"url": "https://api.github.com/repos/firezone/firezone/releases/assets/147443613",
174+
"id": 147443613,
175+
"node_id": "RA_kwDOD12Hpc4Iyc-c",
176+
"name": "firezone-linux-gui-client_amd64.AppImage",
177+
"label": "",
178+
"uploader": {
179+
"login": "github-actions[bot]",
180+
"id": 41898282,
181+
"node_id": "MDM6Qm90NDE4OTgyODI=",
182+
"avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
183+
"gravatar_id": "",
184+
"url": "https://api.github.com/users/github-actions%5Bbot%5D",
185+
"html_url": "https://github.com/apps/github-actions",
186+
"followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
187+
"following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
188+
"gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
189+
"starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
190+
"subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
191+
"organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
192+
"repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
193+
"events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
194+
"received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
195+
"type": "Bot",
196+
"site_admin": false
197+
},
198+
"content_type": "application/octet-stream",
199+
"state": "uploaded",
200+
"size": 8376320,
201+
"download_count": 10,
202+
"created_at": "2024-01-24T04:33:53Z",
203+
"updated_at": "2024-01-24T04:33:53Z",
204+
"browser_download_url": "https://github.com/firezone/firezone/releases/download/1.0.0-pre.8/firezone-linux-gui-client_amd64.AppImage"
205+
},
169206
{
170207
"url": "https://api.github.com/repos/firezone/firezone/releases/assets/147443612",
171208
"id": 147443612,
172209
"node_id": "RA_kwDOD12Hpc4Iyc-c",
173-
"name": "firezone-gui-client-windows-x64.msi",
210+
"name": "firezone-windows-client-x64.msi",
174211
"label": "",
175212
"uploader": {
176213
"login": "github-actions[bot]",
@@ -198,15 +235,19 @@ mod tests {
198235
"download_count": 10,
199236
"created_at": "2024-01-24T04:33:53Z",
200237
"updated_at": "2024-01-24T04:33:53Z",
201-
"browser_download_url": "https://github.com/firezone/firezone/releases/download/1.0.0-pre.8/firezone-gui-client-windows-x64.msi"
238+
"browser_download_url": "https://github.com/firezone/firezone/releases/download/1.0.0-pre.8/firezone-windows-client-x64.msi"
202239
}
203240
]
204241
}"#;
205242

206243
#[test]
207244
fn test() {
245+
let asset_name = super::ASSET_NAME;
208246
let release = super::Release::from_str(RELEASES_LATEST_JSON).unwrap();
209-
assert_eq!(release.browser_download_url.to_string(), "https://github.com/firezone/firezone/releases/download/1.0.0-pre.8/firezone-gui-client-windows-x64.msi");
247+
let expected_url = format!(
248+
"https://github.com/firezone/firezone/releases/download/1.0.0-pre.8/{asset_name}"
249+
);
250+
assert_eq!(release.browser_download_url.to_string(), expected_url);
210251
assert_eq!(release.tag_name.to_string(), "1.0.0-pre.8");
211252

212253
assert!(

0 commit comments

Comments
 (0)