gui: Settings toggle to hide the host QR-code panel
Adds a `show_qr` preference (default on) to GuiSettings, with a checkbox in Settings and a corresponding gate on the host-screen render. Persists to config.toml alongside the existing close-to-tray setting. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+19
-1
@@ -20,13 +20,31 @@ pub struct Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Preferences for the `pixelpass --gui` front-end.
|
/// Preferences for the `pixelpass --gui` front-end.
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct GuiSettings {
|
pub struct GuiSettings {
|
||||||
/// When true, the window's close button hides the app to the system tray
|
/// When true, the window's close button hides the app to the system tray
|
||||||
/// (keeping any live stream running) instead of quitting. Defaults to
|
/// (keeping any live stream running) instead of quitting. Defaults to
|
||||||
/// false — closing quits, which is what people expect.
|
/// false — closing quits, which is what people expect.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub close_to_tray: bool,
|
pub close_to_tray: bool,
|
||||||
|
/// When true, the host screen renders a QR-code panel for the ticket.
|
||||||
|
/// Defaults to true; the toggle exists for users who prefer the plain
|
||||||
|
/// text-only host screen.
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
pub show_qr: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for GuiSettings {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
close_to_tray: false,
|
||||||
|
show_qr: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_true() -> bool {
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Result of the first-run upstream measurement.
|
/// Result of the first-run upstream measurement.
|
||||||
|
|||||||
+38
-7
@@ -596,16 +596,17 @@ pub fn run() -> anyhow::Result<()> {
|
|||||||
};
|
};
|
||||||
// The tray runs on its own thread and wakes us via the proxy.
|
// The tray runs on its own thread and wakes us via the proxy.
|
||||||
let tray = tray::start(proxy.clone());
|
let tray = tray::start(proxy.clone());
|
||||||
let close_to_tray = crate::common::config::load()
|
let gui_settings = crate::common::config::load()
|
||||||
.map(|c| c.gui.close_to_tray)
|
.map(|c| c.gui)
|
||||||
.unwrap_or(false);
|
.unwrap_or_default();
|
||||||
|
|
||||||
let state = PixelPassApp {
|
let state = PixelPassApp {
|
||||||
screen: Screen::default(),
|
screen: Screen::default(),
|
||||||
host: HostState::default(),
|
host: HostState::default(),
|
||||||
viewer: ViewerState::default(),
|
viewer: ViewerState::default(),
|
||||||
tray,
|
tray,
|
||||||
close_to_tray,
|
close_to_tray: gui_settings.close_to_tray,
|
||||||
|
show_qr: gui_settings.show_qr,
|
||||||
waker,
|
waker,
|
||||||
};
|
};
|
||||||
let mut app = App {
|
let mut app = App {
|
||||||
@@ -691,6 +692,14 @@ fn persist_close_to_tray(value: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn persist_show_qr(value: bool) {
|
||||||
|
let mut cfg = crate::common::config::load().unwrap_or_default();
|
||||||
|
cfg.gui.show_qr = value;
|
||||||
|
if let Err(e) = crate::common::config::save(&cfg) {
|
||||||
|
tracing::warn!("failed to save settings: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Which screen the single window is currently showing.
|
/// Which screen the single window is currently showing.
|
||||||
#[derive(Default, PartialEq)]
|
#[derive(Default, PartialEq)]
|
||||||
enum Screen {
|
enum Screen {
|
||||||
@@ -833,6 +842,9 @@ struct PixelPassApp {
|
|||||||
/// hides to the tray instead of quitting. Loaded at startup, written on
|
/// hides to the tray instead of quitting. Loaded at startup, written on
|
||||||
/// toggle in Settings.
|
/// toggle in Settings.
|
||||||
close_to_tray: bool,
|
close_to_tray: bool,
|
||||||
|
/// Persisted preference: render the QR-code panel on the host screen.
|
||||||
|
/// Defaults to on; toggled in Settings.
|
||||||
|
show_qr: bool,
|
||||||
/// Wakes the winit loop when a spawned child emits/exits.
|
/// Wakes the winit loop when a spawned child emits/exits.
|
||||||
waker: Waker,
|
waker: Waker,
|
||||||
}
|
}
|
||||||
@@ -938,6 +950,21 @@ impl PixelPassApp {
|
|||||||
.weak(),
|
.weak(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ui.add_space(12.0);
|
||||||
|
let qr_resp = ui.checkbox(&mut self.show_qr, "Show QR-code panel on the host screen");
|
||||||
|
if qr_resp.changed() {
|
||||||
|
persist_show_qr(self.show_qr);
|
||||||
|
}
|
||||||
|
ui.add_space(4.0);
|
||||||
|
ui.label(
|
||||||
|
egui::RichText::new(
|
||||||
|
"Off: the host screen shows only the ticket text. \
|
||||||
|
Useful when both ends are computers and the QR is just extra clutter.",
|
||||||
|
)
|
||||||
|
.small()
|
||||||
|
.weak(),
|
||||||
|
);
|
||||||
|
|
||||||
// The option does nothing without a tray to hide into; say so plainly.
|
// The option does nothing without a tray to hide into; say so plainly.
|
||||||
if !self.tray.as_ref().is_some_and(TrayHandle::registered) {
|
if !self.tray.as_ref().is_some_and(TrayHandle::registered) {
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
@@ -1127,8 +1154,10 @@ impl PixelPassApp {
|
|||||||
// Lazy QR build: first draw after a Ticket event has `qr_texture =
|
// Lazy QR build: first draw after a Ticket event has `qr_texture =
|
||||||
// None`, so we encode the ticket and load the texture once. The
|
// None`, so we encode the ticket and load the texture once. The
|
||||||
// 4-module quiet zone (white border) matters — phone scanners reject
|
// 4-module quiet zone (white border) matters — phone scanners reject
|
||||||
// QR codes flush against a non-white edge.
|
// QR codes flush against a non-white edge. Skipped when the user
|
||||||
if self.host.qr_texture.is_none()
|
// disabled the QR panel in Settings.
|
||||||
|
if self.show_qr
|
||||||
|
&& self.host.qr_texture.is_none()
|
||||||
&& let Ok(code) = qrcode::QrCode::new(ticket.as_bytes())
|
&& let Ok(code) = qrcode::QrCode::new(ticket.as_bytes())
|
||||||
{
|
{
|
||||||
let w = code.width();
|
let w = code.width();
|
||||||
@@ -1150,7 +1179,9 @@ impl PixelPassApp {
|
|||||||
egui::TextureOptions::NEAREST,
|
egui::TextureOptions::NEAREST,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if let Some(tex) = &self.host.qr_texture {
|
if self.show_qr
|
||||||
|
&& let Some(tex) = &self.host.qr_texture
|
||||||
|
{
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
ui.add(egui::Image::new(tex).fit_to_exact_size(egui::vec2(200.0, 200.0)));
|
ui.add(egui::Image::new(tex).fit_to_exact_size(egui::vec2(200.0, 200.0)));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user