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.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct GuiSettings {
|
||||
/// When true, the window's close button hides the app to the system tray
|
||||
/// (keeping any live stream running) instead of quitting. Defaults to
|
||||
/// false — closing quits, which is what people expect.
|
||||
#[serde(default)]
|
||||
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.
|
||||
|
||||
+38
-7
@@ -596,16 +596,17 @@ pub fn run() -> anyhow::Result<()> {
|
||||
};
|
||||
// The tray runs on its own thread and wakes us via the proxy.
|
||||
let tray = tray::start(proxy.clone());
|
||||
let close_to_tray = crate::common::config::load()
|
||||
.map(|c| c.gui.close_to_tray)
|
||||
.unwrap_or(false);
|
||||
let gui_settings = crate::common::config::load()
|
||||
.map(|c| c.gui)
|
||||
.unwrap_or_default();
|
||||
|
||||
let state = PixelPassApp {
|
||||
screen: Screen::default(),
|
||||
host: HostState::default(),
|
||||
viewer: ViewerState::default(),
|
||||
tray,
|
||||
close_to_tray,
|
||||
close_to_tray: gui_settings.close_to_tray,
|
||||
show_qr: gui_settings.show_qr,
|
||||
waker,
|
||||
};
|
||||
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.
|
||||
#[derive(Default, PartialEq)]
|
||||
enum Screen {
|
||||
@@ -833,6 +842,9 @@ struct PixelPassApp {
|
||||
/// hides to the tray instead of quitting. Loaded at startup, written on
|
||||
/// toggle in Settings.
|
||||
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.
|
||||
waker: Waker,
|
||||
}
|
||||
@@ -938,6 +950,21 @@ impl PixelPassApp {
|
||||
.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.
|
||||
if !self.tray.as_ref().is_some_and(TrayHandle::registered) {
|
||||
ui.add_space(8.0);
|
||||
@@ -1127,8 +1154,10 @@ impl PixelPassApp {
|
||||
// Lazy QR build: first draw after a Ticket event has `qr_texture =
|
||||
// None`, so we encode the ticket and load the texture once. The
|
||||
// 4-module quiet zone (white border) matters — phone scanners reject
|
||||
// QR codes flush against a non-white edge.
|
||||
if self.host.qr_texture.is_none()
|
||||
// QR codes flush against a non-white edge. Skipped when the user
|
||||
// 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 w = code.width();
|
||||
@@ -1150,7 +1179,9 @@ impl PixelPassApp {
|
||||
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(egui::Image::new(tex).fit_to_exact_size(egui::vec2(200.0, 200.0)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user