1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use super::*;
impl App {
pub(super) fn render_system_page(&mut self, ui: &mut egui::Ui) {
theme::page_header(ui, &t!("system_heading"), Some(&t!("system_desc")));
theme::section(ui, &t!("system_section_start"), None, |ui| {
ui.horizontal(|ui| {
ui.checkbox(&mut self.autostart, t!("autostart_label"));
help_marker(ui, &t!("autostart_hint"));
});
ui.add_space(6.0);
ui.horizontal(|ui| {
ui.checkbox(
&mut self.desktop_integration,
t!("desktop_integration_label"),
);
help_marker(ui, &t!("desktop_integration_hint"));
});
// Two conveniences the menu entry doesn't cover. Separate toggles:
// a cabinet wants the desktop icon, a workstation usually wants
// neither. Like every box on this page they only record the choice:
// Finish applies it (`system_apply`), off the UI thread — creating a
// Windows shortcut from the click handler froze the window.
ui.add_space(6.0);
ui.horizontal(|ui| {
ui.checkbox(&mut self.desktop_shortcut, t!("desktop_shortcut_label"));
help_marker(ui, &t!("desktop_shortcut_hint"));
});
// Pinning is shell-specific and we only speak GNOME's dialect, so the
// option simply isn't there on a session we can't serve.
if self.dock_pinning_available {
ui.add_space(6.0);
ui.horizontal(|ui| {
ui.checkbox(&mut self.dock_pinned, t!("dock_pin_label"));
help_marker(ui, &t!("dock_pin_hint"));
});
}
});
// ---- VPinPlay: community ratings, and sharing the table usage.
self.render_vpinplay_section(ui);
// ---- Self-hosted mirror (VBS catalog + VPin media DB). Empty
// = direct GitHub fetch (the default). When set, all index URLs
// and per-asset URLs route through the mirror; the server is
// responsible for rewriting URLs inside the manifests so they
// point back at itself (cf. db.rs::mirror_base_url docs).
theme::section(
ui,
&t!("system_mirror_label"),
Some(&t!("system_mirror_intro")),
|ui| {
help_marker(ui, &t!("system_mirror_hint"));
ui.horizontal(|ui| {
let resp = ui.add(
egui::TextEdit::singleline(&mut self.mirror_base_url)
.hint_text("https://pinready.syl21.org")
.desired_width(420.0),
);
if resp.changed()
&& let Err(e) = self.db.set_mirror_base_url(&self.mirror_base_url)
{
log::error!("Failed to persist mirror_base_url: {e}");
}
if ui
.button(t!("system_mirror_clear"))
.on_hover_text(t!("system_mirror_clear_hint"))
.clicked()
{
self.mirror_base_url.clear();
let _ = self.db.set_mirror_base_url("");
}
});
},
);
// ---- Credits — last wizard page is the natural spot for "thanks
// to" since it's the screen the user sees just before Finish.
// Names sorted alphabetically (case-insensitive).
theme::section(
ui,
&t!("system_credits_title"),
Some(&t!("system_credits_intro")),
|ui| {
for name in [
"Caviar4456",
"Francisdb",
"Jsm174",
"Major Frenchy",
"Somatik",
"Spielfool",
"Superhac",
"Toxie",
"Vbousquet",
] {
ui.label(format!("• {name}"));
}
},
);
// ---- The author's other cabinet projects: name = clickable link,
// then a one-line description.
theme::section(ui, &t!("system_projects_title"), None, |ui| {
for (name, url, desc) in [
(
"rom2altsound",
"https://github.com/Le-Syl21/rom2altsound",
t!("system_projects_rom2altsound"),
),
(
"headtracking",
"https://github.com/Le-Syl21/headtracking",
t!("system_projects_headtracking"),
),
] {
ui.hyperlink_to(name, url);
ui.label(desc);
ui.add_space(6.0);
}
});
}
}