This commit is contained in:
2025-08-06 01:31:20 +02:00
commit 2f0db251b1
5 changed files with 3949 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

3754
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

8
Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "sm-admingate"
version = "0.1.0"
edition = "2024"
[dependencies]
eframe = "0.32.0"
egui = "0.32.0"

BIN
DejaVuSans.ttf Normal file

Binary file not shown.

186
src/main.rs Normal file
View File

@@ -0,0 +1,186 @@
use eframe::egui;
use egui::{Key, RichText};
use std::collections::VecDeque;
use egui::{FontData, FontDefinitions, FontFamily};
use std::sync::{Arc, Mutex};
const MAX_KEYS: usize = 6;
const SECRET_COMBO: [Key; MAX_KEYS] = [
Key::ArrowUp,
Key::ArrowUp,
Key::ArrowDown,
Key::ArrowDown,
Key::ArrowLeft,
Key::ArrowRight,
];
struct AdminGateApp {
key_history: VecDeque<Key>,
should_run_admin_command: Arc<Mutex<bool>>,
}
impl Default for AdminGateApp {
fn default() -> Self {
Self {
key_history: VecDeque::with_capacity(MAX_KEYS),
should_run_admin_command: Arc::new(Mutex::new(false)),
}
}
}
impl eframe::App for AdminGateApp {
fn update(&mut self, ctx: &egui::Context, _: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
ui.vertical_centered(|ui| {
ui.heading("Admin Settings Gate");
ui.add_space(20.0);
// Display last 6 keys
let key_display = self
.key_history
.iter()
.map(|k| match k {
Key::ArrowUp => "",
Key::ArrowDown => "",
Key::ArrowLeft => "",
Key::ArrowRight => "",
_ => "?",
})
.collect::<Vec<_>>()
.join(" ");
ui.label(
RichText::new(&key_display)
.size(60.0)
.strong(),
);
ui.add_space(20.0);
});
});
egui::TopBottomPanel::bottom("footer").show(ctx, |ui| {
ui.horizontal_centered(|ui| {
ui.label(egui::RichText::new("Press ESC to quit. Enter runs the admin command.").size(24.0).weak());
});
});
// Input handling
for event in &ctx.input(|i| i.raw.events.clone()) {
if let egui::Event::Key {
key,
pressed: true,
modifiers: _,
physical_key : _,
repeat: _,
} = event
{
match key {
Key::ArrowUp | Key::ArrowDown | Key::ArrowLeft | Key::ArrowRight => {
if self.key_history.len() == MAX_KEYS {
self.key_history.pop_front();
}
self.key_history.push_back(*key);
//self.should_run_admin_command = false; // reset status
}
Key::Enter => {
if self.key_history.len() == MAX_KEYS
&& self
.key_history
.iter()
.copied()
.eq(SECRET_COMBO.iter().copied())
{
// Run admin command
*self.should_run_admin_command.lock().unwrap() = true;
ctx.send_viewport_cmd(egui::ViewportCommand::Close); // This shuts down the GUI cleanly
}
}
Key::Escape => {
std::process::exit(0);
}
_ => {}
}
}
}
ctx.request_repaint(); // keep UI responsive
}
}
fn setup_custom_fonts(ctx: &egui::Context) {
let mut fonts = FontDefinitions::default();
// Add your custom font
fonts.font_data.insert(
"custom".to_string(),
FontData::from_owned(
std::fs::read("DejaVuSans.ttf").expect("Failed to load font"),
).into(),
);
// Use the custom font for all proportional and monospace text
fonts
.families
.get_mut(&FontFamily::Proportional)
.unwrap()
.insert(0, "custom".to_string());
fonts
.families
.get_mut(&FontFamily::Monospace)
.unwrap()
.insert(0, "custom".to_string());
ctx.set_fonts(fonts);
}
fn main() -> eframe::Result<()> {
let should_run_admin_command = Arc::new(Mutex::new(false));
let shared_flag = should_run_admin_command.clone();
let app = AdminGateApp {
key_history: VecDeque::with_capacity(6),
should_run_admin_command: shared_flag,
};
let options = eframe::NativeOptions::default();
let result = eframe::run_native(
"Admin Gate",
options,
Box::new(|cc| {
// Setup fonts
setup_custom_fonts(&cc.egui_ctx);
Ok(Box::new(app))
}),
);
// After GUI closes
if *should_run_admin_command.lock().unwrap() {
println!("✅ Running admin command...");
match std::process::Command::new("sh")
.arg("-c")
.arg("kitty")
.status() // ← wait until it finishes
{
Ok(status) => {
println!("Admin command exited with: {}", status);
}
Err(e) => {
eprintln!("❌ Failed to run admin command: {}", e);
}
}
}
result
}